
#include <cstdio>
#include <BFile>
#include <BApplication>

#include "ILibStdlib.h"
#include "ILibStdio.h"
#include "ILibMath.h"
#include "ILibBase.h"

#include "member_BSource.h"
#include "member_BClass.h"
#include "member_BScript.h"
#include "member_BObject.h"

using namespace BWE;

member_BSource::member_BSource(BSource* source)
{
	boss = source;
	script = 0;
}
member_BSource::~member_BSource()
{

}

BString& member_BSource::errorMessage(BExp* exp)
{
	if (message.empty())
	{
		message = new BString();
	}
	BString& text = message;
	text.reset();
	if (exp)
	{
		text << exp->info;
	}
	text << " : error : ";
	error = true;
	return text;
}
void member_BSource::raiseMessage(Signal signal)
{
	object_member(boss)->check_emit(signal, message);
	if (script)
	{
		object_member(script)->check_emit(signal, message);
	}
}

bool member_BSource::isType(BString& text)
{
	if (text == "void")
	{
		text.clear();
		return true;
	}
	if (text == "auto")
		return true;
	if (text == "bool")
		return true;
	if (text == "char")
		return true;
	if (text == "byte")
		return true;
	if (text == "short")
		return true;
	if (text == "ushort")
		return true;
	if (text == "int")
		return true;
	if (text == "uint")
		return true;
	if (text == "long")
		return true;
	if (text == "ulong")
		return true;
	if (text == "real")
		return true;
	if (text == "float")
		return true;
	if (text == "double")
		return true;
	if (text == "string")
		return true;
	if (enumMap.contain(text))
		return true;
	if (classMap.contain(text))
		return true;
	if (tempTypes.contain(text))
		return true;
	if (script_member(script)->presetClassMap(text))
		return true;
	if (member_BScript::basicClassMap(text))
		return true;
	return false;
}
bool member_BSource::isName(const BString& text)
{
	if (text.empty())
		return false;
	char c = text[0];
	if (c == '_')
		return true;
	if ('a' <= c && c <= 'z')
		return true;
	if ('A' <= c && c <= 'Z')
		return true;
	return false;
}

StrCit member_BSource::nextWord(BString& word, const BString& text, StrCit& cit, int& line)
{
	while (cit.valid())
	{
		if (cit == '\n')
			line++;
		if (!cit->isSpace())
			break;
		cit++;
	}
	if (cit.index() == text.size())
	{
		word.reset();
		return text.end();
	}
	auto begin = cit;
	if (cit->isDigit())
	{
		auto end = cit + 1;
		while (end.valid())
		{
			if (end == '.')
			{
				if ((end + 1)->isDigit())
				{
					++end;
					continue;
				}
				else
				{
					end++;
					break;
				}
			}
			if (!end->isDigit())
				break;
			++end;
		}
		word.reset(text, begin.index(), end.index());
		cit = end;
		return begin;
	}
	if (cit == ':' && (cit + 1) == ':')
	{
		word = "::";
		cit += 2;
		return begin;
	}
	if (cit == '-' && (cit + 1) == '>')
	{
		word = "->";
		cit += 2;
		return begin;
	}
	if (cit == '/' && (cit + 1) == '*')
	{
		word = "/*";
		cit += 2;
		return begin;
	}
	if (cit == '/' && (cit + 1) == '/')
	{
		word = "//";
		cit += 2;
		return begin;
	}
	if (cit == '\'')
	{
		auto begin = cit++;
		while (cit.valid())
		{
			if (cit == '\'')
				break;
			if (cit == '\n')
				break;
			cit++;
		}
		++cit;
		word.reset(text, begin.index(), cit.index());
		word -= '\n';
		return begin;
	}
	if (cit == '\"')
	{
		auto begin = cit++;
		while (cit.valid())
		{
			if (cit == '\"')
				break;
			if (cit == '\n' && (cit - 1) != '\\')
				break;
			cit++;
		}
		++cit;
		word.reset(text, begin.index(), cit.index());
		word -= '\n';
		return begin;
	}
	if (cit == '.' || cit == ',' || cit == ';' || cit == '(' || cit == ')' || cit == '[' || cit == ']' || cit == '{' || cit == '}')
	{
		word = cit;
		cit += 1;
		return begin;
	}
	if (cit == '+' && (cit + 1) == '+')
	{
		word = "++";
		cit += 2;
		return begin;
	}
	if (cit == '-' && (cit + 1) == '-')
	{
		word = "--";
		cit += 2;
		return begin;
	}
	if (cit == '<' && (cit + 1) == '<')
	{
		word = "<<";
		cit += 2;
		return begin;
	}
	if (cit == '>' && (cit + 1) == '>')
	{
		word = ">>";
		cit += 2;
		return begin;
	}
	if (cit == '&' && (cit + 1) == '&')
	{
		word = "&&";
		cit += 2;
		return begin;
	}
	if (cit == '|' && (cit + 1) == '|')
	{
		word = "||";
		cit += 2;
		return begin;
	}
	if (cit == '<' || cit == '>' || cit == '!' || cit == '+' || cit == '-' || cit == '*' || cit == '/' || cit == '|')
	{
		word = cit;
		if ((cit + 1) == '=')
		{
			word << '=';
			cit += 2;
			return begin;
		}
		++cit;
		return begin;
	}
	if (cit != '_' && cit->isPunct())
	{
		auto end = cit;
		while (end.valid())
		{
			if (end->isSpace())
				break;
			if (cit == '_' || !end->isPunct())
				break;
			end++;
		}
		word.reset(text, begin, end);
		cit = end;
		return begin;
	}
	while (cit.valid())
	{
		if (cit->isSpace())
			break;
		if (cit != '_' && cit->isPunct())
			break;
		++cit;
	}
	word.reset(text, begin, cit);
	return begin;
}

BExp* member_BSource::create(Syntax syntax)
{
	BExp* exp = new BExp(syntax);
	document << exp;
	return exp;
}
BExp* member_BSource::create(Syntax syntax, int line, int begin, int end)
{
	BExp* exp = new BExp(syntax);
	document << exp;
	exp->info << srcnames.last() << ':' << line << '(' << begin << ',' <<  end << ')';
	return exp;
}

BExp* member_BSource::parse(const BString& text, StrCit& cit, int& line)
{
	BExpHolderArray exps;
	BString word;
	while (cit.valid())
	{
		auto begin = nextWord(word, text, cit, line);
		if (word.empty())
			break;
		if (word == "/*")
		{
			BExp* exp = createBlockNote(text, cit, line);
			continue;
		}
		if (word == "//")
		{
			BExp* exp = createLineNote(text, cit, line);
			continue;
		}
		if (word == '#')
		{
			BExp* exp = createMacro(text, cit, line);
			return exp;
		}
		if (word == ',')
		{
			BExp* exp = create(Syntax_Opera, line, begin.count(), cit.count());
			exp->name = word;
			exps.append(exp);
			continue;
		}
		if (word == '(')
		{
			BExp* head = create(Syntax_Opera);
			head->name = word;
			levels.push(exps.size());
			while (BExp* exp = parse(text, cit, line))
			{
				if (exp->name == ')')
				{
					head->name << exp->name;
					head->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' <<  cit.count() << ')';
					if (head->subs.empty())
					{
						head->subs = exp->subs;
						exp->subs.clear();
					}
					if (exp->subs.size())
					{
						BExp* sub = new BExp(Syntax_None);
						sub->subs = exp->subs;
						head->subs.append(sub);
						exp->subs.clear();
					}
					levels.pop();
					break;
				}
				if (exp->syntax == Syntax_Begin || exp->syntax == Syntax_End)
				{
					if (exp->subs.size())
					{
						BExp* sub = analyse(exp->subs);
						head->subs.append(sub);
					}
					exp->subs.reset();
					exps.append(head);
					exp->subs.append(analyse(exps));
					levels.pop();
					errorMessage(exp) << "expect ')', but breaked by '}'.";
					raiseMessage(Signal_Message);
					return exp;
				}
				head->subs.append(exp);
			}
			exps.append(head);
			continue;
		}
		if (word == '[')
		{
			BExp* head = create(Syntax_Opera, line, begin.count(), cit.count());
			head->name = word;
			levels.push(exps.size());
			while (BExp* exp = parse(text, cit, line))
			{
				if (exp->name == ']')
				{
					head->name << exp->name;
					head->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' <<  cit.count() << ')';
					if (head->subs.empty())
					{
						head->subs = exp->subs;
						exp->subs.clear();
					}
					if (exp->subs.size())
					{
						BExp* sub = new BExp(Syntax_None);
						sub->subs = exp->subs;
						head->subs.append(sub);
						exp->subs.clear();
					}
					levels.pop();
					break;
				}
				if (exp->name == '{')
				{
					errorMessage(exp) << "expect ')', block can't contain '{'.";
					raiseMessage(Signal_Message);
					break;
				}
				head->subs.append(exp);
			}
			exps.append(head);
			continue;
		}
		if (word == ')' || word == ']')
		{
			BExp* opera = create(Syntax_Opera, line, begin.count(), cit.count());
			opera->name = word;
			opera->subs = exps;
			return opera;
		}
		if (word == ';')
		{
			BExp* exp = analyse(exps);
			return exp;
		}
		if (word == '{')
		{
			BExp* exp = analyse(exps);
			if (exp)
			{
				BExp* chunk = create(Syntax_Begin, line, begin.count(), cit.count());
				exp->subs.append(chunk);
				while (cit.valid())
				{
					if (BExp* sub = parse(text, cit, line))
					{
						if (sub->syntax == Syntax_End)
						{
							exp->subs.append(sub->subs);
							sub->subs.clear();
							exp->subs.append(sub);
							chunk->value = sub;
							break;
						}
						exp->subs.append(sub);
					}
				}
				BExp* last = exp->subs.last();
				if (last && last->syntax != Syntax_End)
				{
					errorMessage(exp) << "chunk is not completed.";
					raiseMessage(Signal_Message);
				}
			}
			return exp;
		}
		if (word == '}')
		{
			BExp* opera = create(Syntax_End, line, begin.count(), cit.count());
			opera->subs = exps;
			return opera;
		}
		if (word == ':')
		{
			if (exps.last() && exps.last()->syntax == Syntax_Access)
			{
				BExp* exp = analyse(exps);
				return exp;
			}
		}
		if (BExp* exp = createSyntax(word))
		{
			exp->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' << cit.count() << ')';
			exps.append(exp);
			continue;
		}
		if (BExp* exp = createAccess(word))
		{
			exp->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' << cit.count() << ')';
			exps.append(exp);
			continue;
		}
		if (BExp* exp = createValue(word))
		{
			exp->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' << cit.count() << ')';
			exps.append(exp);
			continue;
		}
		if (BExp* exp = createOpera(word))
		{
			exp->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' << cit.count() << ')';
			exps.append(exp);
			continue;
		}
		if (isType(word))
		{
			BExp* exp = create(Syntax_Type, line, begin.count(), cit.count());
			exp->type = word;
			exps.append(exp);
			continue;
		}
		BExp* exp = create(Syntax_Name, line, begin.count(), cit.count());
		exp->name = word;
		exps.append(exp);
		if (!isName(word))
		{
			errorMessage(exp) << word << "is invalid name.";
			raiseMessage(Signal_Message);
		}
	}
	BExp* exp = analyse(exps);
	return exp;
}
BExp* member_BSource::analyse(BExpHolderArray& exps)
{
	if (exps.empty())
	{
		return 0;
	}
	if (exps.size() == 1)
	{
		return exps[0];
	}

	for (int i = 0; i < exps.size() - 1; i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Name)
		{
			if (VariantInfo* vinfo = findVariant(exp->name))
			{
				exp->type = vinfo->type;
				exp->value = vinfo->value;
			}
		}
		if (exp->syntax == Syntax_Inline)
		{
			exps.remove(i--);
			continue;
		}
		BExp* next = exps(i + 1);
		if (exp->syntax == Syntax_Const)
		{
			if (next && next->syntax == Syntax_Type)
			{
				next->type.prepend("const ");
				exps.remove(i--);
				continue;
			}
		}
		if (exp->syntax == Syntax_Type && next->name == '*')
		{
			exp->type << '*';
			exps.remove(i + 1);
			continue;
		}
		if (exp->syntax == Syntax_Type && next->name == '&')
		{
			exp->type << '&';
			exps.remove(i + 1);
			continue;
		}
		if (exp->syntax == Syntax_Type && next->name == '<')
		{
			int count = 0;
			for (int j = i + 2; j < exps.size(); j++)
			{
				if (exps[j]->name == '>')
					break;
				count++;
			}
			next->name = "<>";
			next->subs.append(exps, i + 2, count);
			exps.remove(i + 1, count + 2);
			collateParams(next->subs);
			exp->params = next->subs;
			createTempClass(exp);
			i--;
			continue;
		}
		if (exp->syntax == Syntax_Template)
		{
			if (next->name != '<')
			{
				errorMessage(exp) << "template should followed by <>.";
				raiseMessage(Signal_Message);
				continue;
			}
			int count = 0;
			for (int j = i + 2; j < exps.size(); j++)
			{
				if (exps[j]->name == '>')
					break;
				count++;
			}
			next->subs.append(exps, i + 2, count);
			collateParams(next->subs);
			exp->params = next->subs;
			exps.remove(i + 1, count + 2);
			continue;
		}
		if (exp->syntax == Syntax_Case || exp->syntax == Syntax_Default)
		{
			BExp* over = 0;
			int end = i;
			while (++end < exps.size())
			{
				BExp* exp = exps[end];
				if (exp->name == ':')
				{
					over = exp;
					break;
				}
			}
			if (!over)
			{
				errorMessage(exp) << exp->name << " the case is not finished.";
				raiseMessage(Signal_Message);
				return exp;
			}
			exp->params.append(exps, i + 1, end - i - 1);
			exps.remove(i + 1, end - i);
			continue;
		}
		if (exp->syntax == Syntax_Return)
		{
			exp->subs.append(exps, i + 1, exps.size());
			exps.remove(i + 1, exps.size());
			BExp* param = analyse(exp->subs);
			exp->params.append(param);
			exp->subs.clear();
			continue;
		}
	}

	for (int i = 0; i < exps.size(); i++)
	{
		BExp* prev = exps(i - 1);
		BExp* exp = exps[i];
		BExp* next = exps(i + 1);
		if (exp->syntax == Syntax_For)
		{
			if (i > 0)
			{
				errorMessage(exp) << exp->name << " should be first word of expression." << exp->name;
				raiseMessage(Signal_Message);
				return 0;
			}
			exp->params = next->subs;
			exp->subs.append(exps, 2, exps.size());
			if (next->name != "()")
			{
				errorMessage(exp) << exp->name << "for should follow '(exp;bool;exp)'." << exp->name;
				raiseMessage(Signal_Message);
			}
			return exp;
		}
		if (exp->syntax == Syntax_If || exp->syntax == Syntax_While || exp->syntax == Syntax_Switch)
		{
			if (i > 0)
			{
				errorMessage(exp) << exp->name << " should be first word of expression." << exp->name;
				raiseMessage(Signal_Message);
				return 0;
			}
			if (next->name != "()")
			{
				errorMessage(next) << exp->name << " has no parameter." << next->name;
				raiseMessage(Signal_Message);
				return 0;
			}
			exp->params = next->subs;
			collateParams(exp->params);
			if (exps.size() > 2)
			{
				exp->subs.append(exps, 2, exps.size());
				BExp* first = exp->subs.first();
				if (first->syntax != Syntax_Begin)
				{
					BExp* sub = analyse(exp->subs);
					exp->subs.reset();
					exp->subs.append(new BExp(Syntax_Begin));
					exp->subs.append(sub);
					exp->subs.append(new BExp(Syntax_End));
				}
			}
			return exp;
		}
		if (exp->syntax == Syntax_Else)
		{
			if (i > 0)
			{
				errorMessage(exp) << "else should be first word of expression." << exp->name;
				raiseMessage(Signal_Message);
				return 0;
			}
			if (exps.size() > 1)
			{
				exps.remove(0);
				exp->subs.reset();
				exp->subs.append(analyse(exps));
			}
			BExp* first = exp->subs.first();
			if (first && first->syntax != Syntax_Begin)
			{
				BExp* sub = analyse(exp->subs);
				exp->subs.reset();
				exp->subs.append(new BExp(Syntax_Begin));
				exp->subs.append(sub);
				exp->subs.append(new BExp(Syntax_End));
			}
			return exp;
		}
		if (exp->syntax == Syntax_New)
		{
			if (next->syntax != Syntax_Type)
			{
				errorMessage(next) << " unknown type " << next->name;
				raiseMessage(Signal_Message);
			}
			exp->type = next->type;
			if (BExp* after = exps(i + 2))
			{
				if (after->name == "()")
				{
					exp->params = after->subs;
					collateParams(exp->params);
				}
				else
				{
					errorMessage(after) << after->type << "should be () for parameters.";
					raiseMessage(Signal_Message);
				}
			}
			return exp;
		}
		if (exp->syntax == Syntax_Enum && next && next->syntax == Syntax_Name)
		{
			exp->name = next->name;
			next->syntax = Syntax_Type;
			next->type = next->name;
			next->name.clear();
			enumMap.insert(exp->name);
			return exp;
		}
		if (exp->syntax == Syntax_Class && next && next->syntax == Syntax_Name)
		{
			exp->name = next->name;
			next->syntax = Syntax_Type;
			next->type = next->name;
			next->name.clear();
			if (prev && prev->syntax == Syntax_Template)
			{
				exp->value = prev;
				exps.remove(--i);
			}
			if (BExp* after = exps(i + 2))
			{
				if (after->syntax != Syntax_Opera || after->name != ':')
				{
					errorMessage(after) << "class declare failed." << after->name;
					raiseMessage(Signal_Message);
				}
				else
				{
					exp->params.append(exps, i + 3, exps.size());
					if (exp->params.size() == 1)
					{
						BExp* param = exp->params[0];
						if (param->syntax != Syntax_Type)
						{
							errorMessage(param) << param->name << " is not class defined.";
							raiseMessage(Signal_Message);
						}
						param->syntax = Syntax_Access;
						param->value = BClass::Access_Private;
						param->name = "private";
						param->subs.clear();
					}
					else if (exp->params.size() == 2)
					{
						BExp* param = exp->params[0];
						BExp* second = exp->params[1];
						if (param->syntax != Syntax_Access)
						{
							errorMessage(param) << "class inherit restrict failed.";
							raiseMessage(Signal_Message);
						}
						if (second->syntax != Syntax_Type)
						{
							errorMessage(second) << second->name << " is not class defined.";
							raiseMessage(Signal_Message);
						}
						if (second->type.empty())
						{
							errorMessage(second) << "class is undeclared.";
							raiseMessage(Signal_Message);
						}
						param->type = second->type;
						exp->params.remove(1);
					}
					else if (exp->params.size() > 2)
					{
						BExp* param = exp->params[1];
						errorMessage(param) << "class inherit list is too much.";
						raiseMessage(Signal_Message);
					}
				}
			}
			tempTypes.append(exp->name);
			return exp;
		}
		if (exp->syntax == Syntax_Name && prev && prev->syntax == Syntax_Type)
		{
			if (next && next->name == "()")
			{
				bool isfunc = true;
				collateParams(next->subs);
				for (int i = 0; i < next->subs.size(); i++)
				{
					BExp* sub = next->subs[i];
					if (sub->syntax != Syntax_Decl)
					{
						isfunc = false;
						break;
					}
				}
				if (isfunc)
				{
					exp->syntax = Syntax_Function;
					exp->type = prev->type;
					exp->params = next->subs;
					if (BExp* before = exps(i - 2))
					{
						if (before->syntax == Syntax_Virtual)
						{
							exp->name.prepend("[virtual]");
						}
					}
					if (BExp* after = exps(i + 2))
					{
						if (after->syntax == Syntax_Const)
						{
							exp->name.append("[const]");
							exps.remove(i + 2);
						}
					}
					if (exps.size() - i > 2)
					{
						BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
						suffixes.append(exps, i + 2, exps.size() - i - 2);
					}
					return exp;
				}
			}
			if (next && next->name == "[]")
			{
				BExp* array = new BExp(Syntax_Array);
				array->info = exp->info;
				array->name = exp->name;
				array->type << "array<" << prev->type << '>';
				array->params = next->subs;
				array->subs.append(exps, i + 2, exps.size());
				BExp* first = exps.first();
				if (first && first->syntax == Syntax_Extern)
				{
					array->value = Syntax_Extern;
					exps.remove(0, 1);
				}
				return array;
			}
			BExp* decl = new BExp(Syntax_Decl);
			decl->info = exp->info;
			decl->type = prev->type;
			decl->name = exp->name;
			exp->type = decl->type;
			exp->value = decl;
			int end = findSplit(exps);
			decl->params.append(exps, i + 1, end - 2);
			if (BExp* param = analyse(decl->params))
			{
				decl->params.reset();
				decl->params.append(param);
			}
			exps.remove(i - 1, end + 1);
			BExp* first = exps.first();
			if (first && first->syntax == Syntax_Extern)
			{
				decl->value = Syntax_Extern;
				exps.remove(0, 1);
			}
			if (exps.size())
			{
				errorMessage(exp) << "decl syntax must be alone.";
				raiseMessage(Signal_Message);
				BExp* none = create(Syntax_None);
				none->subs = exps;
				none->subs.append(decl);
				return none;
			}
			return decl;
		}
		if (exp->syntax == Syntax_Opera && exp->name == '=')
		{
			exp->params.append(exps, i + 1, exps.size() - i - 1);
			BExpHolder ret = analyse(exp->params);
			if (ret)
			{
				exp->params.reset();
				exp->params.append(ret);
			}
			exps.remove(i + 1, exps.size());
			continue;
		}
	}

	if (exps.size() > 1
		&& exps[0]->syntax == Syntax_Type
		&& exps[1]->name == "()")
	{
		BExp* exp = exps[0];
		exp->syntax = Syntax_Method;
		exp->name = exp->type;
		exp->params = exps[1]->subs;
		if (!collateParams(exp->params))
		{
			return 0;
		}
		exp->type.clear();
		if (exps.size() > 2)
		{
			exps.remove(0, 2);
			if (exps[0]->name == ':')
			{
				exps.remove(0);
				BExp* suffix = analyse(exps);
				exp->value = suffix;
			}
		}
		return exp;
	}

	if (exps.size() > 1
		&& exps[0]->name == '~'
		&& exps[1]->syntax == Syntax_Type
		&& exps[2]->name == "()")
	{
		BExp* opera = exps[2];
		if (!collateParams(opera->subs))
		{
			return 0;
		}
		BExp* exp = exps[1];
		exp->syntax = Syntax_Method;
		exp->name << exps[0]->name << exp->type;
		exp->params = opera->subs;
		exp->type.clear();
		return exp;
	}

	if (exps.size() >= 3
		&& exps[0]->syntax == Syntax_Type
		&& exps[1]->name == "::"
		&& exps[2]->syntax == Syntax_Type
		&& exps[3]->name == "()")
	{
		if (exps[0]->type != exps[2]->type)
		{
			errorMessage(exps[2]) << "Constructor declare failed.";
			raiseMessage(Signal_Message);
		}
		if (!collateParams(exps[3]->subs))
		{
			return 0;
		}
		BExp* exp = exps[2];
		exp->syntax = Syntax_Method;
		exp->info = exps[0]->info;
		exp->name << exp->type << "::" << exp->type;
		exp->params = exps[3]->subs;
		exp->type.clear();
		if (exps.size() > 4)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 4, exps.size() - 4);
			if (exps[4]->syntax == Syntax_Opera && exps[4]->name == ':')
			{
				suffixes.remove(0);
				collateParams(suffixes);
				for (int i = 0; i < suffixes.size(); i++)
				{
					BExpHolder suffix = suffixes[i];
					suffixes[i] = analyse(suffix->subs);
				}
			}
		}
		return exp;
	}

	if (exps.size() >= 5
		&& exps[0]->syntax == Syntax_Type
		&& exps[1]->name == "::"
		&& exps[2]->name == '~'
		&& exps[3]->syntax == Syntax_Type
		&& exps[4]->name == "()")
	{
		if (exps[0]->type != exps[3]->type)
		{
			errorMessage(exps[2]) << "Constructor declare failed.";
			raiseMessage(Signal_Message);
		}
		if (exps[4]->subs.size())
		{
			errorMessage(exps[4]) << "destructor can't have parameters.";
			raiseMessage(Signal_Message);
		}
		BExp* exp = exps[3];
		exp->syntax = Syntax_Method;
		exp->info = exps[0]->info;
		exp->name << exp->type << "::~" << exp->type;
		exp->type.clear();
		if (exps.size() > 5)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 5, exps.size() - 5);
		}
		return exp;
	}

	if (exps.size() >= 5
		&& exps[0]->syntax == Syntax_Type
		&& exps[1]->syntax == Syntax_Type
		&& exps[2]->name == "::"
		&& exps[3]->syntax == Syntax_Name
		&& exps[4]->name == "()")
	{
		if (!collateParams(exps[4]->subs))
		{
			return 0;
		}
		BExp* exp = exps[3];
		exp->syntax = Syntax_Method;
		exp->info = exps[0]->info;
		exp->type = exps[0]->type;
		exp->name.prepend("::");
		exp->name.prepend(exps[1]->type);
		exp->params = exps[4]->subs;
		if (exps.size() > 5)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 5, exps.size() - 5);
		}
		return exp;
	}

	if (exps.size() == 1)
	{
		return exps[0];
	}
	BExp* exp = new BExp(Syntax_None);
	exp->info = exps[0]->info;
	exp->subs = exps;
	return exp;
}
BExp* member_BSource::createMacro(const BString& text, StrCit& cit, int& line)
{
	BString word;
	auto begin = nextWord(word, text, cit, line);
	if (word == "include")
	{
		BExp* include = create(Syntax_Include, line, begin.count(), cit.count());
		begin = nextWord(word, text, cit, line);
		cit = text.find('\n', cit);
		text.substr(word, begin, cit);
		word.trimmed();
		BExp* param = create(Syntax_File, line, begin.count(), cit.count());
		param->name = word;
		include->params.append(param);
		if (word.beginWith('<') && word.endWith('>'))
		{
			word.remove('<');
			word.remove('>');
			if (includes.contain(include))
				return include;
			include->name = word;
			include->value = includeLibrary(word);
			includes.append(include);
			if (include->value.empty())
			{
				const BString& text = script_member(script)->cacheFile(word);
				if (text.size())
				{
					srcnames.push(word);
					includeText(include, text);
					srcnames.pop();
				}
				else
				{
					errorMessage(param) << "include file failed : " << word;
					raiseMessage(Signal_Message);
				}
			}
			return include;
		}
		if (word.beginWith('\"') && word.endWith('\"'))
		{
			word.remove('\"');
			word.remove('\"');
			if (srcnames.contain(word))
			{
				errorMessage(param) << "loop include file failed " << word;
				raiseMessage(Signal_Message);
				return include;
			}
			if (BSource* source = script->source(word))
			{
				if (source_member(source)->text.size())
				{
					srcnames.push(word);
					includeText(include, source_member(source)->text);
					srcnames.pop();
				}
				return include;
			}
			BString& text = cachedFileMap[word];
			if (text.empty())
			{
				BFile::Load(word, text);
			}
			if (text.size())
			{
				srcnames.push(word);
				includeText(include, text);
				srcnames.pop();
			}
			else
			{
				errorMessage(param) << "include file failed : " << word;
				raiseMessage(Signal_Message);
			}
			return include;
		}
		errorMessage(param) << "include file failed " << word;
		raiseMessage(Signal_Message);
		return include;
	}
	BExp* none = new BExp(Syntax_None);
	errorMessage(none) << word << "is invalid macro.";
	raiseMessage(Signal_Message);
	return none;
}
BExp* member_BSource::createLineNote(const BString& text, StrCit& cit, int& line)
{
	BExp* exp = create(Syntax_Note);
	auto begin = cit - 2;
	while (cit.valid())
	{
		if (cit++ == '\n')
		{
			line++;
			break;
		}
	}
	exp->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' << cit.count() << ')';
	return exp;
}
BExp* member_BSource::createBlockNote(const BString& text, StrCit& cit, int& line)
{
	BExp* exp = create(Syntax_Note);
	auto begin = cit - 2;
	exp->info << srcnames.last() << ':' << line;
	while (cit.valid())
	{
		if (cit == '\n')
		{
			line++;
			cit++;
			continue;
		}
		if (cit++ == '*' && cit++ == '/')
		{
			break;
		}
	}
	exp->info << srcnames.last() << ':' << line << '(' << begin.count() << ',' << cit.count() << ')';
	exp->value = line;
	return exp;
}
BExp* member_BSource::createSyntax(const BString& word)
{
	if (word == "this")
		return create(Syntax_This);
	if (word == "self")
		return create(Syntax_Self);
	if (word == "new")
		return create(Syntax_New);
	if (word == "if")
		return create(Syntax_If);
	if (word == "else")
		return create(Syntax_Else);
	if (word == "for")
		return create(Syntax_For);
	if (word == "while")
		return create(Syntax_While);
	if (word == "switch")
		return create(Syntax_Switch);
	if (word == "case")
		return create(Syntax_Case);
	if (word == "default")
		return create(Syntax_Default);
	if (word == "continue")
		return create(Syntax_Continue);
	if (word == "break")
		return create(Syntax_Break);
	if (word == "return")
		return create(Syntax_Return);
	if (word == "enum")
		return create(Syntax_Enum);
	if (word == "template")
		return create(Syntax_Template);
	if (word == "class")
		return create(Syntax_Class);
	if (word == "struct")
		return create(Syntax_Struct);
	if (word == "const")
		return create(Syntax_Const);
	if (word == "extern")
		return create(Syntax_Extern);
	if (word == "virtual")
		return create(Syntax_Virtual);
	return 0;
}
BExp* member_BSource::createAccess(BString& word)
{
	if (word == "public")
	{
		BExp* exp = create(Syntax_Access);
		exp->name = word;
		exp->value = BClass::Access_Public;
		return exp;
	}
	if (word == "protected")
	{
		BExp* exp = create(Syntax_Access);
		exp->name = word;
		exp->value = BClass::Access_Protected;
		return exp;
	}
	if (word == "private")
	{
		BExp* exp = create(Syntax_Access);
		exp->name = word;
		exp->value = BClass::Access_Private;
		return exp;
	}
	return 0;
}
BExp* member_BSource::createValue(BString& word)
{
	if (word[0] == '\"')
	{
		BExp* exp = create(Syntax_Value);
		word.remove(0);
		if (word.empty())
			return exp;
		if (word.endWith('\"'))
		{
			word -= '\"';
		}
		else
		{
			errorMessage(exp) << "string is not finished.";
			raiseMessage(Signal_Message);
		}
		word.replace("\\n", '\n');
		word.replace("\\t", '\t');
		word.replace("\\r", '\r');
		exp->type = "string";
		exp->value = word;
		return exp;
	}
	if (word[0] == '\'')
	{
		BExp* exp = create(Syntax_Value);
		word.remove(0);
		if (word.empty())
			return exp;
		if (word.endWith('\''))
		{
			word -= '\'';
		}
		else
		{
			errorMessage(exp) << "string is not finished.";
			raiseMessage(Signal_Message);
		}
		word.replace("\\n", '\n');
		word.replace("\\t", '\t');
		word.replace("\\r", '\r');
		if (word.size() > 1)
		{
			errorMessage(exp) << "\'X\' is should be a charater.";
			raiseMessage(Signal_Message);
		}
		exp->type = "char";
		exp->value = word[0];
		return exp;
	}
	if (word == "true")
	{
		BExp* exp = create(Syntax_Value);
		exp->type = "bool";
		exp->value = true;
		return exp;
	}
	if (word == "false")
	{
		BExp* exp = create(Syntax_Value);
		exp->type = "bool";
		exp->value = false;
		return exp;
	}
	if (word == "null")
	{
		BExp* exp = create(Syntax_Value);
		exp->type = "auto";
		return exp;
	}
	if (word.isNumber())
	{
		BExp* exp = create(Syntax_Value);
		if (word.contain('.'))
		{
			if (word.endWith('f'))
			{
				float v = word.toFloat();
				exp->type = "float";
				exp->value = v;
			}
			else
			{
				double v = word.toDouble();
				exp->type = "double";
				exp->value = v;
			}
		}
		else
		{
			if (word.endWith("ul"))
			{
				unsigned long long v = word.toLong();
				exp->type = "ulong";
				exp->value = v;
			}
			else if (word.endWith('l'))
			{
				long long v = word.toLong();
				exp->type = "long";
				exp->value = v;
			}
			else
			{
				int v = word.toInt();
				exp->type = "int";
				exp->value = v;
			}
		}
		return exp;
	}
	for (int i = 0; i < enumMap.size(); i++)
	{
		auto it = enumMap.seek(i);
		const BString& type = it.key();
		if (it.value().empty())
			continue;
		BEnum* enm = *it;
		if (enm->contain(word))
		{
			BExp* exp = create(Syntax_Key);
			exp->type = type;
			exp->name = word;
			exp->value = enm->value(word);
			return exp;
		}
	}
	return 0;
}
BExp* member_BSource::createOpera(BString& word)
{
	if (word == "->")
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		return exp;
	}
	if (word == ':' || word == "::" || word == '.')
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		return exp;
	}

	if (word == '~' || word == '!' || word == '&' || word == "++" || word == "--")
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		exp->value = 0;
		return exp;
	}

	if (word == '*' || word == '/' || word == '%')
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		exp->value = 1;
		return exp;
	}

	if (word == '+' || word == '-')
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		exp->value = 2;
		return exp;
	}

	if (word == '<' || word == '>' || word == "==" || word == "!=" || word == "<=" || word == ">=")
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		exp->value = 3;
		return exp;
	}

	if (word == "<<" || word == ">>")
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		exp->value = 3;
		return exp;
	}

	if (word == "=" || word == "+=" || word == "-=" || word == "*=" || word == "/=")
	{
		BExp* exp = create(Syntax_Opera);
		exp->name = word;
		exp->value = 4;
		return exp;
	}

	if (word == "&&")
	{
		BExp* exp = create(Syntax_And);
		exp->name = word;
		return exp;
	}
	if(word == "||")
	{
		BExp* exp = create(Syntax_Or);
		exp->name = word;
		return exp;
	}

	return 0;
}
bool member_BSource::collateParams(BExpHolderArray& exps)
{
	if (exps.empty())
		return true;
	if (exps.size() == 1)
	{
		BExp* exp = exps.first();
		if (exp->syntax == Syntax_None || exp->syntax == Syntax_Opera)
		{
			return checkExp(exp);
		}
		return true;
		if (exp->subs.size())
		{
			if (BExp* decl = analyse(exp->subs))
			{
				exps.replace(exp, decl);
			}
		}
	}
	else
	{
		int begin = 0;
		for (int i = 0; i < exps.size(); i++)
		{
			BExp* exp = exps[i];
			if (exp->syntax == Syntax_Opera && exp->name == ',')
			{
				int count = i - begin;
				if (count > 1)
				{
					exp->subs.append(exps, begin, count);
					BExp* param = analyse(exp->subs);
					exps.remove(begin, count);
					exps[begin] = param;
					exp->subs.clear();
				}
				else
				{
					exps.remove(i);
				}
				i = begin++;
			}
		}
		if (begin > 0)
		{
			int count = exps.size() - begin;
			if (count > 1)
			{
				BExpHolderArray subs(exps, begin, count);
				BExp* exp = analyse(subs);
				exps.remove(begin, count);
				exps.append(exp);
			}
		}
		else
		{
			BExp* param = analyse(exps);
			exps.reset();
			exps.append(param);
		}
	}
	return true;
}
bool member_BSource::includeText(BExp* include, const BString& text)
{
	StrCit cit = text.begin();
	int line = 0;
	while (cit.valid())
	{
		this->tempTypes.clear();
		if (BExp* exp = parse(text, cit, line))
		{
			this->checkExp(exp);
			if (exp->syntax == Syntax_Decl || exp->syntax == Syntax_Array)
			{
				for (int i = 0; i < declares.size(); i++)
				{
					BExp* decl = declares[i];
					if (decl->name == exp->name)
					{
						errorMessage(exp) << exp->name << " is already declared.";
						raiseMessage(Signal_Message);
					}
				}
				declares.append(exp);
			}
			include->subs.append(exp);
		}
	}
	return true;
}
ILibrary* member_BSource::includeLibrary(const BString& libname)
{
	if (libname == "cstdio" || libname == "stdio.h")
	{
		return ILibStdio::Instance();
	}
	if (libname == "cstdlib" || libname == "stdlib.h")
	{
		return ILibStdlib::Instance();
	}
	if (libname == "cmath" || libname == "math.h")
	{
		return ILibMath::Instance();
	}
	if (libname == "cbase" || libname == "base.h")
	{
		return ILibBase::Instance();
	}
	return 0;
}
void member_BSource::organizeLevel(BExp* exp)
{
	for (int i = 0; i < exp->subs.size(); i++)
	{
		if (BExp* sub = exp->subs[i])
		{
			sub->up = exp;
			organizeLevel(sub);
		}
	}
	for (int i = 0; i < exp->params.size(); i++)
	{
		if (BExp* param = exp->params[i])
		{
			param->up = exp;
			organizeLevel(param);
		}
	}
}

bool member_BSource::checkExp(BExp* exp)
{
	if (!exp)
		return false;
	switch (exp->syntax)
	{
	case Syntax_None:
	{
		if (exp->type.empty())
		{
			exp->type = checkFormula(exp->subs);
		}
		return true;
	}
	case Syntax_Note:
		return true;
	case Syntax_Include:
		return true;
	case Syntax_File:
		return true;
	case Syntax_New:
		return checkNew(exp);
	case Syntax_Assign:
		return checkAssign(exp);
	case Syntax_Array:
		return checkArray(exp);
	case Syntax_Begin:
	{
		VariantInfo& res = stack.push();
		res.value = Syntax_Begin;
		return true;
	}
	case Syntax_End:
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			VariantInfo& var = stack[i];
			if (var.value == Syntax_Begin)
			{
				stack.back(i);
				return true;
			}
		}
		errorMessage(exp) << "} has no pair of {.";
		raiseMessage(Signal_Message);
		return false;
	case Syntax_Value:
		return true;
	case Syntax_Decl:
		return checkDecl(exp);
	case Syntax_Name:
		return checkName(exp);
	case Syntax_Self:
		return checkSelf(exp);
	case Syntax_Opera:
		return checkOpera(exp);
	case Syntax_Call:
		return checkCall(exp);
	case Syntax_Test:
		return checkTest(exp);
	case Syntax_And:
	case Syntax_Or:
		return checkAndOr(exp);
	case Syntax_If:
		return checkIf(exp);
	case Syntax_Else:
		return checkElse(exp);
	case Syntax_While:
		return checkWhile(exp);
	case Syntax_For:
		return checkFor(exp);
	case Syntax_Switch:
		return checkSwitch(exp);
	case Syntax_Case:
		return checkCase(exp);
	case Syntax_Break:
		return checkBreak(exp);
	case Syntax_Default:
		return checkDefault(exp);
	case Syntax_Continue:
		return checkContinue(exp);
	case Syntax_Return:
		return checkReturn(exp);
	case Syntax_Enum:
		return checkEnum(exp);
	case Syntax_Key:
		return true;
	case Syntax_Class:
		return checkClass(exp);
	case Syntax_Method:
		return checkMethod(exp);
	case Syntax_Function:
		return checkFunction(exp);
	default:
		return false;
	}
	return !error;
}
bool member_BSource::checkArray(BExp* exp)
{
	BClass* cls = findClass(exp->type);
	VariantInfo& var = stack.push();
	var.type = exp->type;
	var.name = exp->name;
	var.value = cls;
	if (!cls)
	{
		errorMessage(exp) << "class " << exp->type << " is not declared.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (exp->value == Syntax_Extern)
	{
		return true;
	}
	int size = 0;
	if (BExp* param = exp->params.first())
	{
		checkExp(param);
		if (param->syntax != Syntax_Value || param->type != "int" || exp->params.size() != 1)
		{
			errorMessage(param) << " format of array init should be '[int]'." << ".";
			raiseMessage(Signal_Message);
		}
		exp->value = param->value;
		size = param->value;
		exp->params.clear();
	}
	if (exp->subs.size())
	{
		BExp* assign = exp->subs.first();
		if (!assign || assign->name != '=')
		{
			errorMessage(assign) << " = should follow " << exp->type << ".";
			raiseMessage(Signal_Message);
			return false;
		}
		BExp* begin = exp->subs(1);
		if (!begin || begin->syntax != Syntax_Begin)
		{
			errorMessage(begin) << " = { should follow " << exp->type << ".";
			raiseMessage(Signal_Message);
			return false;
		}
		BExp* end = exp->subs(2);
		if (!end || end->syntax != Syntax_End)
		{
			errorMessage(end) << " = {  } should follow " << exp->type << ".";
			raiseMessage(Signal_Message);
			return false;
		}
		exp->subs = end->subs;
		collateParams(exp->subs);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		if (size && size != exp->subs.size())
		{
			errorMessage(exp) << " array size should equal size of values." << ".";
			raiseMessage(Signal_Message);
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			BExp* opera = new BExp(Syntax_Opera);
			opera->name = "<<";
			opera->params << exp->subs[i];
			findMethod(opera, cls);
			exp->subs[i] = opera;
		}
		BExp* name = new BExp(Syntax_Name);
		name->type = exp->type;
		name->name = exp->name;
		exp->subs.insert(0, name);
		exp->subs.prepend(begin);
		exp->subs.append(end);
	}
	return true;
}
bool member_BSource::checkAssign(BExp* exp)
{
	return true;
}
bool member_BSource::checkNew(BExp* exp)
{
	if (exp->type.empty())
		return false;

	BClass* cls = findClass(exp->type);
	if (!cls)
	{
		errorMessage(exp) << "class " << exp->type << " is not declared.";
		raiseMessage(Signal_Message);
		return false;
	}
	for (int i = 0; i < exp->params.size(); i++)
	{
		checkExp(exp->params[i]);
	}
	if (exp->params.empty())
	{
		BExp* init = new BExp(Syntax_Init);
		init->name = exp->type;
		init->value = findMethod(init, cls);
		if (init->value.empty())
		{
			errorMessage(exp) << "invalid construct " << exp->type << "::" << init->name;
			raiseMessage(Signal_Message);
		}
		exp->subs.append(init);
	}
	else if (exp->params.size() == 1)
	{
		BExp* param = exp->params.first();
		if (param->name == '=')
		{
			BExp* init = new BExp(Syntax_Init);
			init->name << exp->type << "(" << param->type << ")";
			init->value = class_member(cls)->methodMap(init->name);
			if (init->value.empty())
			{
				init->name.reset();
				init->name << "=(" << param->type << ")";
				init->value = class_member(cls)->methodMap(init->name);
				if (init->value.empty())
				{
					errorMessage(exp) << "invalid operation : assign " << param->type << " to " << exp->type;
					raiseMessage(Signal_Message);
				}
			}
			init->name.prepend("::");
			init->name.prepend(exp->type);
			exp->subs.append(init);
		}
		else if (param->type.size())
		{
			BExp* init = new BExp(Syntax_Init);
			init->name = exp->type;
			init->params.append(param);
			init->value = findMethod(init, cls);
			if (init->value.empty())
			{
				errorMessage(exp) << "invalid construct : " << param->type << " to " << exp->type;
				raiseMessage(Signal_Message);
			}
			exp->subs.append(init);
		}
		else
		{
			errorMessage(exp) << "invalid declare expression.";
			raiseMessage(Signal_Message);
		}
	}
	else
	{
		BExp* init = new BExp(Syntax_Init);
		init->name = exp->type;
		init->params = exp->params;
		init->value = findMethod(init, cls);
		if (init->value.empty())
		{
			errorMessage(exp) << "invalid construct : " << exp->type;
			raiseMessage(Signal_Message);
		}
		exp->subs.append(init);
	}
	return true;
}
bool member_BSource::checkDecl(BExp* exp)
{
	if (exp->subs.size())
		return true;
	if (exp->params.size() > 1)
	{
		errorMessage(exp) << "too many expressions after decl.";
		raiseMessage(Signal_Message);
	}
	BExp* param = exp->params.first();
	if (param)
	{
		checkExp(param);
		if (exp->type == "auto")
			exp->type = param->type;
	}
	if (exp->name.size())
	{
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			VariantInfo& var = stack[i];
			if (CallInfo* cinfo = var.value)
				break;
			if (var.value == Syntax_Begin)
				break;
			if (var.name == exp->name)
			{
				errorMessage(exp) << "variant " << exp->type << ' ' << exp->name << " is redeclared.";
				raiseMessage(Signal_Message);
			}
		}
	}
	if (exp->type.contain("auto"))
	{
		VariantInfo& var = stack.push();
		var.type = exp->type;
		var.name = exp->name;
		if (param->name == '=')
		{
			param->syntax = Syntax_Assign;
			exp->subs.append(param);
		}
		return true;
	}
	if (exp->type.endWith('&') || exp->type.endWith('*'))
	{
		BClass* cls = findClass(exp->type);
		if (!cls)
		{
			errorMessage(exp) << "class " << exp->type << " is not declared.";
			raiseMessage(Signal_Message);
			return false;
		}
		exp->value = cls;
		VariantInfo& var = stack.push();
		var.type = exp->type;
		var.name = exp->name;
		var.value = cls;
		if (exp->value == Syntax_Extern)
		{
			if (exp->params.size())
			{
				errorMessage(exp) << "extern decl can't be inited : " << exp->type;
				raiseMessage(Signal_Message);
				return false;
			}
			return true;
		}
		if (BExp* param = exp->params.first())
		{
			if (param->type.contain("auto"))
			{
				param->syntax = Syntax_Assign;
				exp->subs.append(param);
				return true;
			}
			if (checkType(cls, param->type))
			{
				param->syntax = Syntax_Assign;
				exp->subs.append(param);
				return true;
			}
			if (class_member(cls)->checkInherit(param->type))
			{
				BExp* cast = new BExp(Syntax_Cast);
				cast->type = exp->type;
				param->syntax = Syntax_Assign;
				param->params.append(cast);
				param->type = exp->type;
				exp->subs.append(param);
				return true;
			}
			if (BClass* right_cls = findClass(param->type))
			{
				if (class_member(right_cls)->checkInherit(exp->type))
				{
					param->syntax = Syntax_Assign;
					exp->subs.append(param);
					return true;
				}
			}
			if (exp->type.beginWith("const "))
			{
				BString type;
				exp->type.word(type, 6);
				if (type == param->type)
					return true;
				type << '&';
				if (type == param->type)
					return true;
			}
			errorMessage(exp) << "assign failed " << exp->type << " from " << param->type;
			raiseMessage(Signal_Message);
			return false;
		}
		return true;
	}
	if (BEnum* enm = findEnum(exp->type))
	{
		VariantInfo& var = stack.push();
		var.type = exp->type;
		var.name = exp->name;
		var.value = enm;
		if (exp->value == Syntax_Extern)
		{
			return true;
		}
		BClass* cls = this->findClass("int");
		if (exp->params.empty())
		{
			BString initName;
			initName << exp->type << "()";
			if (MethodInfo* minfo = class_member(cls)->methodMap(initName))
			{
				BExp* init = new BExp(Syntax_Init);
				init->name = initName;
				init->value = minfo;
				init->name.prepend("::");
				init->name.prepend(exp->type);
				exp->subs.append(init);
			}
			return true;
		}
		BExp* param = exp->params.first();
		if (param->name == '=')
		{
			BString methodName;
			methodName << "int(int)";
			if (MethodInfo* minfo = class_member(cls)->methodMap(methodName))
			{
				BExp* init = new BExp(Syntax_Init);
				init->name = methodName;
				init->name.prepend("int::");
				init->value = minfo;
				exp->subs.append(param->params);
				exp->subs.append(init);
				return true;
			}
			errorMessage(exp) << "invalid operation : assign " << param->type << " to " << exp->type;
			raiseMessage(Signal_Message);
			return false;
		}
		if (param->type.size())
		{
			BExp* init = new BExp(Syntax_Init);
			init->name = exp->type;
			init->params.append(param);
			findMethod(init, cls);
			init->params.clear();
			if (init->value.empty())
			{
				errorMessage(exp) << "invalid operation : init " << param->type << " to " << exp->type;
				raiseMessage(Signal_Message);
				return false;
			}
			exp->subs.append(param);
			exp->subs.append(init);
			return true;
		}
		if (param->name == "()")
		{
			BExp* init = new BExp(Syntax_Init);
			init->name = exp->type;
			init->params = param->subs;
			findMethod(init, cls);
			if (init->value.empty())
			{
				errorMessage(exp) << "invalid operation : no init method " << this->funcName(init);
				raiseMessage(Signal_Message);
				return false;
			}
			exp->subs.append(init);
			return true;
		}
		if (enm->name() == param->type)
		{
			exp->subs.append(param);
			return true;
		}
		if (exp->type.beginWith("const "))
		{
			BString type;
			exp->type.word(type, 6);
			if (type == param->type)
			{
				exp->subs.append(param);
				return true;
			}
			type << '&';
			if (type == param->type)
			{
				exp->subs.append(param);
				return true;
			}
		}
		return true;
	}
	if (BClass* cls = findClass(exp->type))
	{
		VariantInfo& var = stack.push();
		var.type = exp->type;
		var.name = exp->name;
		var.value = cls;
		if (exp->value == Syntax_Extern)
		{
			return true;
		}
		if (exp->params.empty())
		{
			BString initName;
			initName << exp->type << "()";
			if (MethodInfo* minfo = class_member(cls)->methodMap(initName))
			{
				BExp* init = new BExp(Syntax_Init);
				init->name = initName;
				init->value = minfo;
				init->name.prepend("::");
				init->name.prepend(exp->type);
				exp->subs.append(init);
			}
			return true;
		}
		if (param->name == '=')
		{
			if (param->type.contain("auto"))
			{
				param->syntax = Syntax_Assign;
				exp->subs.append(param);
				return true;
			}
			BExpHolder init = new BExp(Syntax_Init);
			init->name = exp->type;
			init->params.append(param->params);
			init->value = findMethod(init, cls);
			if (init->value.valid())
			{
				exp->params.clear();
				exp->subs.clear();
				exp->subs.append(init);
				return true;
			}
			if (checkType(cls, param->type))
			{
				param->syntax = Syntax_Assign;
				exp->subs.append(param);
				return true;
			}
			if (class_member(cls)->checkInherit(param->type))
			{
				BExp* cast = new BExp(Syntax_Cast);
				cast->type = exp->type;
				param->syntax = Syntax_Assign;
				param->params.append(cast);
				param->type = exp->type;
				exp->subs.append(param);
				return true;
			}
			if (BClass* right_cls = findClass(param->type))
			{
				if (class_member(right_cls)->checkInherit(exp->type))
				{
					param->syntax = Syntax_Assign;
					exp->subs.append(param);
					return true;
				}
			}
			errorMessage(exp) << "invalid operation : assign " << param->type << " to " << exp->type;
			raiseMessage(Signal_Message);
			return false;
		}
		if (param->name == "()")
		{
			BExp* init = new BExp(Syntax_Init);
			init->name = exp->type;
			init->params = param->subs;
			findMethod(init, cls);
			if (init->value.empty())
			{
				errorMessage(exp) << "invalid operation : no init method " << this->funcName(init);
				raiseMessage(Signal_Message);
				return false;
			}
			exp->subs.append(init);
			return true;
		}
		if (param->type.size())
		{
			BExp* init = new BExp(Syntax_Init);
			init->name = exp->type;
			init->params.append(param);
			findMethod(init, cls);
			init->params.clear();
			if (init->value.empty())
			{
				errorMessage(exp) << "invalid operation : init " << param->type << " to " << exp->type;
				raiseMessage(Signal_Message);
				return false;
			}
			exp->subs.append(param);
			exp->subs.append(init);
			return true;
		}
		errorMessage(exp) << "invalid declare expression.";
		raiseMessage(Signal_Message);
		return false;
	}
	errorMessage(exp) << "class " << exp->type << " is not declared.";
	raiseMessage(Signal_Message);
	return false;
}
bool member_BSource::checkName(BExp* exp)
{
	if (exp->subs.empty())
	{
		if (VariantInfo* vinfo = findVariant(exp->name))
		{
			exp->type = vinfo->type;
			exp->value = vinfo->value;
			return true;
		}
		if (BClass* self = findSelf())
		{
			if (VariantInfo* vinfo = class_member(self)->findVariant(exp->name))
			{
				exp->syntax = Syntax_Self;
				exp->type = vinfo->type;
				return true;
			}
		}
		errorMessage(exp) << exp->name << " is not declared.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (VariantInfo* vinfo = findVariant(exp->subs))
	{
		exp->type = vinfo->type;
		return true;
	}
	if (BClass* self = findSelf())
	{
		if (VariantInfo* vinfo = class_member(self)->findVariant(exp->subs.first()->name))
		{
			for (int i = 1; i < exp->subs.size(); i++)
			{
				BExp* sub = exp->subs[i];
				BClass* cls = findClass(vinfo->type);
				if (!cls)
					break;
				vinfo = class_member(cls)->findVariant(sub->name);
				if (!vinfo)
					break;
				sub->type = vinfo->type;
			}
			if (vinfo)
			{
				exp->syntax = Syntax_Self;
				exp->type = vinfo->type;
				return true;
			}
		}
	}
	return false;
}
bool member_BSource::checkSelf(BExp* exp)
{
	BClass* self = 0;
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		if (CallInfo* cinfo = vinfo.value)
		{
			self = cinfo->self;
			exp->type = vinfo.type;
			break;
		}
	}
	if (!self)
	{
		errorMessage(exp) << "self is unfound.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (exp->subs.empty())
	{
		VariantInfo* vinfo = class_member(self)->findVariant(exp->name);
		if (!vinfo)
		{
			errorMessage(exp) << exp->name << " is unfound.";
			raiseMessage(Signal_Message);
			return false;
		}
		exp->type = vinfo->type;
		return true;
	}
	for (int i = 0; i < exp->subs.size(); i++)
	{
		BExp* sub = exp->subs[i];
		if (sub->syntax == Syntax_Opera && sub->name == '.')
		{
			exp->subs.remove(i--);
			continue;
		}
	}
	BExp* first = exp->subs.first();
	VariantInfo* vinfo = class_member(self)->findVariant(first->name);
	if (!vinfo)
	{
		errorMessage(first) << first->name << " is unfound.";
		raiseMessage(Signal_Message);
		return false;
	}
	for (int i = 1; i < exp->subs.size(); i++)
	{
		BExp* sub = exp->subs[i];
		if (BClass* cls = findClass(vinfo->type))
		{
			vinfo = class_member(cls)->findVariant(sub->name);
			if (!vinfo)
			{
				errorMessage(exp) << exp->name << " is not declared.";
				raiseMessage(Signal_Message);
				break;
			}
			exp->type = vinfo->type;
		}
		else
		{
			errorMessage(exp) << vinfo->type << "::" << exp->name << " is not declared.";
			raiseMessage(Signal_Message);
			return false;
		}
	}
	exp->type = vinfo->type;
	if (exp->subs.size())
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			exp->name << exp->subs[i]->name << '.';
		}
		exp->name -= '.';
		exp->subs.clear();
	}
	return true;
}
bool member_BSource::checkOpera(BExp* exp)
{
	if (exp->subs.empty())
	{
		if (exp->name == '=')
		{
			exp->type = checkFormula(exp->params);
			return true;
		}
		return false;
	}
	if (exp->name == "++")
	{
		checkExp(exp->subs(0));
		exp->type = exp->subs(0)->type;
		return this->applyOpera(exp);
	}
	if (exp->name == "--")
	{
		checkExp(exp->subs(0));
		exp->type = exp->subs(0)->type;
		return this->applyOpera(exp);
	}
	if (exp->name == '+' && exp->params.empty())
	{
		checkExp(exp->subs(0));
		exp->type = exp->subs(0)->type;
		return this->applyOpera(exp);
	}
	if (exp->name == '-' && exp->params.empty())
	{
		checkExp(exp->subs(0));
		exp->type = exp->subs(0)->type;
		return this->applyOpera(exp);
	}
	if (exp->name == "()")
	{
		exp->type = checkFormula(exp->subs);
		return true;
	}
	if (BExp* sub = exp->subs(0))
	{
		checkExp(sub);
		exp->type = sub->type;
	}
	if (exp->params.size())
	{
		checkFormula(exp->params);
	}
	if (exp->name == '=')
	{
		BExp* left = exp->subs(0);
		if (left->type.beginWith("const"))
		{
			errorMessage(exp) << "can't assign const value : " << left->type << '.';
			raiseMessage(Signal_Message);
			return false;
		}
		if (left->type.endWith('&') || left->type.endWith('*'))
		{
			exp->syntax = Syntax_Assign;
			return true;
		}
	}
	return applyOpera(exp);
}
bool member_BSource::checkCall(BExp* exp)
{
	if (MethodInfo* minfo = exp->value)
		return true;
	for (int i = 0; i < exp->params.size(); i++)
	{
		checkExp(exp->params[i]);
	}
	VariantInfo* vinfo = exp->value;
	if (!vinfo && exp->subs.size())
	{
		vinfo = findVariant(exp->subs);
		if (!vinfo)
			return false;
	}
	if (vinfo)
	{
		if (BClass* cls = vinfo->value)
		{
			if (!findMethod(exp, cls))
			{
				BString& text = errorMessage(exp);
				text << "method " << cls->name() << "::" << exp->name << '(';
				for (int i = 0; i < exp->params.size(); i++)
				{
					BExp* param = exp->params[i];
					text << param->type << ',';
				}
				text -= ',';
				text << ") is not declared.";
				raiseMessage(Signal_Message);
				return false;
			}
			return true;
		}
		errorMessage(exp) << "class " << vinfo->name << " is lost.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (FuncInfo* finfo = findFunction(exp))
	{
		exp->type = finfo->type;
		exp->value = finfo;
		return true;
	}
	errorMessage(exp) << "function " << exp->name << " is not declared.";
	raiseMessage(Signal_Message);
	return false;
}
bool member_BSource::checkTest(BExp* exp)
{
	BExp* param = exp->params.first();
	if (param && param->syntax == Syntax_Decl)
	{
		BExp* name = new BExp(Syntax_Name);
		name->type = param->type;
		name->name = param->name;
		checkExp(name);
		exp->subs.append(name);
	}
	if (exp->type == "byte")
		return true;
	if (exp->type == "char")
		return true;
	if (exp->type == "short")
		return true;
	if (exp->type == "int")
		return true;
	if (exp->type == "long")
		return true;
	if (exp->type == "real")
		return true;
	if (exp->type == "float")
		return true;
	if (exp->type == "double")
		return true;
	return true;
}
bool member_BSource::checkAndOr(BExp* exp)
{
	if (BExp* prev = exp->subs.first())
	{
		checkExp(prev);
		if (prev->syntax == Syntax_Decl)
		{
			errorMessage(prev) << exp->name << " can't used with declare.";
			raiseMessage(Signal_Message);
		}
		else if (prev->type != "bool")
		{
			BExp* test = new BExp(Syntax_Test);
			test->params.append(prev);
			checkExp(test);
			exp->subs[0] = test;
		}
	}
	else
	{
		errorMessage(exp) << exp->name << " must has left value.";
		raiseMessage(Signal_Message);
	}
	if (BExp* next = exp->params.first())
	{
		checkExp(next);
		if (next->syntax == Syntax_Decl)
		{
			errorMessage(next) << exp->name << " can't used with declare.";
			raiseMessage(Signal_Message);
		}
		else if (next->type != "bool")
		{
			BExp* test = new BExp(Syntax_Test);
			test->params.append(next);
			checkExp(test);
			exp->params[0] = test;
		}
	}
	else
	{
		errorMessage(exp) << exp->name << " must has right value.";
		raiseMessage(Signal_Message);
	}
	exp->type = "bool";
	return true;
}
bool member_BSource::checkIf(BExp* exp)
{
	if (exp->params.empty())
	{
		errorMessage(exp) << "if need single bool param. if (bool)";
		raiseMessage(Signal_Message);
		return false;
	}
	if (exp->params.size() > 1)
	{
		errorMessage(exp) << "if has to many params.";
		raiseMessage(Signal_Message);
		return false;
	}
	int top = stack.size();
	if (BExp* param = exp->params[0])
	{
		checkExp(param);
		if (param->type != "bool")
		{
			BExpHolder test = new BExp(Syntax_Test);
			test->info = param->info;
			test->type = "bool";
			test->params = exp->params;
			if (!checkExp(test))
			{
				errorMessage(param) << "if param should be bool, failed to test " << param->type << ".";
				raiseMessage(Signal_Message);
				return false;
			}
			exp->params[0] = test;
		}
	}
	checkSubs(exp);
	stack.back(top);
	return true;
}
bool member_BSource::checkElse(BExp* exp)
{
	int top = stack.size();
	checkSubs(exp);
	stack.back(top);
	return !error;
}
bool member_BSource::checkWhile(BExp* exp)
{
	if (exp->params.empty())
	{
		errorMessage(exp) << "while need single bool param : while (bool).";
		raiseMessage(Signal_Message);
		return false;
	}
	if (BExp* second = exp->params(1))
	{
		errorMessage(second) << "while has to many params.";
		raiseMessage(Signal_Message);
		return false;
	}
	int top = stack.size();
	if (BExp* param = exp->params[0])
	{
		checkExp(param);
		if (param->type != "bool")
		{
			BExp* decl = new BExp(Syntax_Decl);
			decl->info = param->info;
			decl->type = "bool";
			decl->params = exp->params;
			if (!checkExp(decl))
			{
				errorMessage(param) << "if param should be bool, failed to convert " << param->type << " to bool.";
				raiseMessage(Signal_Message);
			}
			exp->params[0] = decl;
		}
	}
	stack.push().value = Syntax_While;
	checkSubs(exp);
	stack.back(top);
	return true;
}
bool member_BSource::checkFor(BExp* exp)
{
	if (exp->params.size() != 3)
	{
		errorMessage(exp) << "for need three params : for (exp;bool;exp).";
		raiseMessage(Signal_Message);
	}
	int top = stack.size();
	for (int i = 0; i < exp->params.size(); i++)
	{
		checkExp(exp->params[i]);
	}
	if (exp->params.size() > 1)
	{
		BExp* second = exp->params[1];
		if (second->type != "bool")
		{
			BExp* decl = new BExp(Syntax_Decl);
			decl->info = second->info;
			decl->type = "bool";
			decl->params = exp->params;
			if (!checkExp(decl))
			{
				errorMessage(second) << "for second param should be bool, failed to convert " << second->type << " to bool.";
				raiseMessage(Signal_Message);
			}
			exp->params[1] = decl;
		}
	}
	stack.push().value = Syntax_For;
	if (exp->subs.size())
	{
		BExp* first = exp->subs.first();
		if (first->syntax != Syntax_Begin)
		{
			BExp* sub = analyse(exp->subs);
			sub->type = checkFormula(exp->subs);
			exp->subs.clear();
			exp->subs.append(sub);
		}
		checkSubs(exp);
	}
	stack.back(top);
	return true;
}
bool member_BSource::checkSwitch(BExp* exp)
{
	if (exp->params.empty())
	{
		errorMessage(exp) << "switch need single integer param : switch(integer).";
		raiseMessage(Signal_Message);
		return false;
	}
	if (BExp* second = exp->params(1))
	{
		errorMessage(second) << "switch has to many params.";
		raiseMessage(Signal_Message);
		return false;
	}
	BMap<int, BExpHolder> keyMap;
	for (int i = 0; i < exp->subs.size(); i++)
	{
		BExp* sub = exp->subs[i];
		BExp* first = sub->subs.first();
		if (first && (first->syntax == Syntax_Case || first->syntax == Syntax_Default))
		{
			exp->subs.insert(i--, first);
			sub->subs.remove(0);
			continue;
		}
		if (!checkExp(sub))
			continue;
		if (sub->syntax == Syntax_Case)
		{
			int key = sub->value;
			if (keyMap.contain(key))
			{
				errorMessage(sub) << "key " << sub->params.first()->name << " has been cased.";
				raiseMessage(Signal_Message);
				continue;
			}
			keyMap.insert(key, sub);
		}
	}
	return true;
}
bool member_BSource::checkCase(BExp* exp)
{
	if (exp->params.empty())
	{
		errorMessage(exp) << "case must have a integer parameter.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (exp->params.size() > 1)
	{
		errorMessage(exp) << "case has too many params.";
		raiseMessage(Signal_Message);
		return false;
	}
	BExp* param = exp->params.first();
	if (!param->value.is<int>())
	{
		errorMessage(param) << "case param must be integer.";
		raiseMessage(Signal_Message);
		return false;
	}
	exp->value = param->value;
	return true;
}
bool member_BSource::checkBreak(BExp* exp)
{
	VariantInfo* loop = 0;
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		if (vinfo.value == Syntax_While || vinfo.value == Syntax_For)
		{
			loop = &vinfo;
			break;
		}
		if (vinfo.value == Syntax_Function)
		{
			break;
		}
	}
	if (!loop)
	{
		errorMessage(exp) << "continue is out of loop syntax.";
		raiseMessage(Signal_Message);
		return false;
	}
	return true;
}
bool member_BSource::checkDefault(BExp* exp)
{
	if (exp->params.size())
	{
		errorMessage(exp) << "default should has no parameter.";
		raiseMessage(Signal_Message);
		return false;
	}
	return true;
}
bool member_BSource::checkContinue(BExp* exp)
{
	VariantInfo* loop = 0;
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		if (vinfo.value == Syntax_While || vinfo.value == Syntax_For)
		{
			loop = &vinfo;
			break;
		}
		if (vinfo.value == Syntax_Function)
		{
			break;
		}
	}
	if (!loop)
	{
		errorMessage(exp) << "continue is out of loop syntax.";
		raiseMessage(Signal_Message);
		return false;
	}
	return true;
}
bool member_BSource::checkReturn(BExp* exp)
{
	VariantInfo* loop = 0;
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		if (vinfo.value == Syntax_Function)
			break;
	}
	for (int i = 0; i < exp->params.size(); i++)
	{
		checkExp(exp->params[i]);
	}
	CallInfo* cinfo = 0;
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		cinfo = vinfo.value;
		if (cinfo)
			break;
	}
	if (cinfo == 0)
	{
		errorMessage(exp) << "return used out of function.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (cinfo->type.size() && exp->params.empty())
	{
		errorMessage(exp) << "return value of type " << cinfo->type;
		raiseMessage(Signal_Message);
		return false;
	}
	if (cinfo->type.empty() && exp->params.size())
	{
		errorMessage(exp) << "should return nothing here." << cinfo->type;
		raiseMessage(Signal_Message);
		return false;
	}
	if (BExp* param = exp->params.first())
	{
		if (param->type.empty())
		{
			if (cinfo->type.endWith('&') || cinfo->type.endWith('*'))
				return true;
		}
		if (cinfo->type != param->type)
		{
			if (cinfo->type.endWith('&') && param->type == "auto")
				return true;
			BExpHolder decl = new BExp(Syntax_Decl);
			decl->info = param->info;
			decl->type = cinfo->type;
			decl->params.reset();
			decl->params.append(param);
			if (checkExp(decl))
			{
				exp->params.reset();
				exp->params.append(decl);
				return true;
			}
			errorMessage(param) << "function return type don't match.";
			raiseMessage(Signal_Message);
			return false;
		}
	}
	return true;
}
bool member_BSource::checkEnum(BExp* exp)
{
	if (exp->subs.empty())
	{
		return true;
	}
	if (BEnum* enm = enumMap[exp->name])
	{
		errorMessage(exp) << "enum " << exp->name << "is redeclared.";
		raiseMessage(Signal_Message);
		return false;
	}
	BExp* last = exp->subs.last();
	if (!last)
		return true;
	exp->subs.insert(1, last->subs);
	last->subs.clear();
	BEnum* enm = new BEnum(exp->name);
	enm->setAsset(exp);
	int key_pos = 0;
	int equal_pos = 0;
	int value_pos = 0;
	for (int i = 0; i < exp->subs.size(); i++)
	{
		BExp* sub = exp->subs[i];
		if (sub->syntax == Syntax_Begin && i == 0)
			continue;
		if (sub->syntax == Syntax_End && i == exp->subs.size() - 1)
			continue;
		if (sub->syntax == Syntax_Name)
		{
			key_pos = i;
			continue;
		}
		if (sub->syntax == Syntax_Value)
		{
			value_pos = i;
			continue;
		}
		if (sub->syntax == Syntax_Opera && sub->name == '=')
		{
			equal_pos = i;
			continue;
		}
		if (sub->syntax == Syntax_Opera && sub->name == ',')
		{
			BExp* keyExp = exp->subs[key_pos];
			if (enm->contain(keyExp->name))
			{
				errorMessage(keyExp) << " has been declared.";
				raiseMessage(Signal_Message);
				continue;
			}
			if (i - key_pos == 1)
			{
				keyExp->type = exp->name;
				keyExp->syntax = Syntax_Key;
				enm->append(keyExp->name);
				keyExp->value = enm->value(keyExp->name);
				continue;
			}
			if (equal_pos <= key_pos)
			{
				errorMessage(sub) << "invalid expression in enum-key declaration.";
				raiseMessage(Signal_Message);
				continue;
			}
			BExp* valueExp = exp->subs[equal_pos + 1];
			if (valueExp->type != "int")
			{
				errorMessage(valueExp) << "value of enum should be integer.";
				raiseMessage(Signal_Message);
				continue;
			}
			keyExp->syntax = Syntax_Key;
			keyExp->type = exp->name;
			keyExp->value = valueExp->value;
			enm->append(keyExp->name, valueExp->value);
			continue;
		}
		errorMessage(sub) << "invalid expression in class declaration.";
		raiseMessage(Signal_Message);
	}
	enumMap[exp->name] = enm;
	return true;
}
bool member_BSource::checkClass(BExp* exp)
{
	BClass* cls = classMap[exp->name];
	if (cls)
	{
		errorMessage(exp) << "class " << exp->name << "is redeclared.";
		raiseMessage(Signal_Message);
		return false;
	}
	cls = new BClass(exp->name);
	classMap[exp->name] = cls;
	if (BExp* temp = exp->value)
	{
		if (temp->syntax == Syntax_Template)
		{
			for (int i = 0; i < temp->params.size(); i++)
			{
				BExp* param = temp->params[i];
				class_member(cls)->tempTypes.append(param->name);
			}
			return true;
		}
	}
	class_member(cls)->inherits = exp->params;
	for (int i = 0; i < exp->params.size(); i++)
	{
		BExp* param = exp->params[i];
		if (BClass* super = findClass(param->type))
		{
			param->value = super;
			continue;
		}
		errorMessage(exp) << "super class " << exp->name << " is not declared.";
		raiseMessage(Signal_Message);
	}
	BClass::Access access = BClass::Access_Private;
	for (int i = 0; i < exp->subs.size(); i++)
	{
		BExp* sub = exp->subs[i];
		if (sub->syntax == Syntax_Begin && i == 0)
			continue;
		if (sub->syntax == Syntax_End && i == exp->subs.size() - 1)
			continue;
		if (sub->syntax == Syntax_Access)
		{
			access = sub->value;
			continue;
		}
		if (sub->syntax == Syntax_Decl)
		{
			if (class_member(cls)->variants.contain(sub->name))
			{
				errorMessage(exp) << "class insert variant failed : " << exp->name << "is existed.";
				raiseMessage(Signal_Message);
				continue;
			}
			class_member(cls)->declares.append(sub);
			VariantInfo& varinfo = class_member(cls)->variants.append();
			varinfo.type = sub->type;
			varinfo.name = sub->name;
			varinfo.access = access;
			continue;
		}
		if (sub->syntax == Syntax_Method || sub->syntax == Syntax_Function)
		{
			MethodInfo* minfo = new MethodInfo(cls);
			minfo->type = sub->type;
			minfo->access = access;
			sub->syntax = Syntax_Method;
			if (sub->subs.size())
			{
				minfo->method = sub;
			}
			if (sub->name.beginWith("[virtual]"))
			{
				minfo->virt = true;
				sub->name.remove("[virtual]");
			}
			if (sub->name.endWith("[const]"))
			{
				minfo->cnst = true;
				sub->name -= "[const]";
			}
			minfo->name = sub->name;
			BString funcName = this->funcName(sub);
			if (class_member(cls)->methodMap.contain(funcName))
			{
				errorMessage(exp) << "class insert variant failed : " << exp->name << "is existed.";
				raiseMessage(Signal_Message);
				continue;
			}
			class_member(cls)->methodMap[funcName] = minfo;
			for (int i = 0; i < sub->params.size(); i++)
			{
				BExp* param = sub->params[i];
				ParamInfo& pinfo = minfo->params.append();
				pinfo.type = param->type;
				pinfo.name = param->name;
			}
			if (BExpHolderArray* suffixes = sub->value)
			{
				if (suffixes->size() == 2 && suffixes->first()->name == '=' && (*suffixes)[1]->value == 0)
				{
					if (minfo->virt)
					{
						minfo->method = 0;
					}
					else
					{
						errorMessage(suffixes->first()) << "method is not virtual, can't assign 0.";
						raiseMessage(Signal_Message);
					}
				}
				else
				{
					errorMessage(suffixes->first()) << "method suffix is invalid.";
					raiseMessage(Signal_Message);
				}
			}
			continue;
		}
		errorMessage(sub) << "invalid expression in class declaration.";
		raiseMessage(Signal_Message);
	}
	int top = stack.size();
	for (int i = 0; i < class_member(cls)->declares.size(); i++)
	{
		BExp* decl = class_member(cls)->declares[i];
		this->checkExp(decl);
	}
	stack.back(top);
	for (int i = 0; i < exp->subs.size(); i++)
	{
		BExp* sub = exp->subs[i];
		if (sub->syntax == Syntax_Method && sub->subs.size())
		{
			sub->name.prepend("::");
			sub->name.prepend(exp->name);
			checkExp(sub);
		}
	}
	return true;
}
bool member_BSource::checkMethod(BExp* exp)
{
	BString type;
	int split = exp->name.word(type, 0);
	exp->name.remove(0, split + 2);
	bool isConst = false;
	if (exp->name.endWith("[const]"))
	{
		isConst = true;
		exp->name -= "[const]";
	}
	bool isConstructor = (type == exp->name);
	BClass* cls = findClass(type);
	if (!cls)
	{
		errorMessage(exp) << "class " << type << " is not declared.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (exp->name.empty())
	{
		exp->syntax = Syntax_None;
		exp->type = type;

		BExp* value = new BExp(Syntax_Value);
		value->type = type;
		exp->subs.append(value);

		BExp* init = new BExp(Syntax_Init);
		init->name = type;
		init->params = exp->params;
		init->value = findMethod(init, cls);
		if (init->value.empty())
		{
			errorMessage(exp) << "invalid operation : no init method " << this->funcName(init);
			raiseMessage(Signal_Message);
		}
		exp->subs.append(init);
		exp->params.clear();
		return true;
	}
	exp->name = this->funcName(exp);
	MethodInfo* minfo = class_member(cls)->methodMap(exp->name);
	if (!minfo)
	{
		errorMessage(exp) << exp->type << ' ' << exp->name << " is not declared.";
		raiseMessage(Signal_Message);
		return false;
	}
	if (minfo->method != exp)
	{
		if (minfo->cnst != isConst)
		{
			errorMessage(exp) << "method " << exp->type << "::" << exp->name << " is const.";
			raiseMessage(Signal_Message);
			return false;
		}
		if (minfo->method.valid() && exp->subs.size())
		{
			errorMessage(exp) << "method " << exp->type << ' ' << exp->name << " is redeclared.";
			raiseMessage(Signal_Message);
			return false;
		}
		minfo->method = exp;
	}

	int top = stack.size();
	CallInfo* cinfo = new CallInfo();
	cinfo->top = top;
	cinfo->type = exp->type;
	cinfo->self = cls;
	VariantInfo& res = stack.push();
	res.type = type;
	res.name = exp->name;
	res.value = cinfo;
	for (int i = 0; i < exp->params.size(); i++)
	{
		BExp* param = exp->params[i];
		VariantInfo& var = stack.push();
		var.type = param->type;
		var.name = param->name;
		var.value = findClass(param->type);
		if (var.value.empty())
		{
			if (!tempTypes.contain(param->type))
			{
				errorMessage(param) << "class " << param->type << " is undeclared.";
				raiseMessage(Signal_Message);
			}
		}
	}
	checkSubs(exp);
	stack.back(top);
	if (isConstructor)
	{
		BMap<BString, BExpHolder> initMap;
		if (BExp* suffix = exp->value)
		{
			if (suffix->syntax == Syntax_Const)
			{
				errorMessage(suffix) << "Constructor can not be const.";
				raiseMessage(Signal_Message);
			}
			if (suffix->syntax != Syntax_Method)
			{
				errorMessage(suffix) << "expression is invalid here.";
				raiseMessage(Signal_Message);
			}
			if (!class_member(cls)->checkInherit(suffix->name))
			{
				errorMessage(suffix) << type << " is not inherit from " << suffix->name;
				raiseMessage(Signal_Message);
			}
			if (this->findClass(suffix->name))
			{
				suffix->syntax = Syntax_Call;
				BString type = suffix->name;
				suffix->name << "::" << type << "()";
				initMap.insert(type, suffix);
			}
		}
		for (int i = 0; i < class_member(cls)->inherits.size(); i++)
		{
			const BString& type = class_member(cls)->inherits[i]->type;
			if (initMap.contain(type))
				continue;
			BClass* up = class_member(cls)->inherits[i]->value;
			if (!up)
				continue;
			BExp* call = new BExp(Syntax_Call);
			call->name << type << "::" << type << "()";
			initMap.insert(type, call);
		}
		for (int i = 0; i < class_member(cls)->variants.size(); i++)
		{
			VariantInfo& vinfo = class_member(cls)->variants[i];
			if (BExp* decl = vinfo.value)
			{
				exp->subs.prepend(decl->subs);
			}
		}
		for (auto it = initMap.begin(); it.valid(); it++)
		{
			BExp* call = *it;
			call->subs.append(new BExp(Syntax_Self));
			exp->subs.prepend(call);
		}
	}
	else
	{
		if (BExpHolderArray* suffixes = exp->value)
		{
			BExp* first = suffixes->first();
			if (first && first->syntax == Syntax_Const)
			{
				minfo->cnst = true;
			}
		}
	}
	return !error;
}
bool member_BSource::checkFunction(BExp* exp)
{
	exp->name = this->funcName(exp);
	FuncInfo* func = this->functionMap(exp->name);
	if (!func)
	{
		func = new FuncInfo();
		for (int i = 0; i < exp->params.size(); i++)
		{
			BExp* param = exp->params[i];
			ParamInfo& pinfo = func->params.append();
			pinfo.type = param->type;
			if (pinfo.type.beginWith("const "))
			{
				pinfo.type.remove("const ");
				pinfo.cnst = true;
			}
			if (pinfo.type.endWith('*') || pinfo.type.endWith('&'))
			{
				pinfo.refe = pinfo.type.last();
				pinfo.type -= pinfo.refe;
			}
			pinfo.name = param->name;
		}
		this->functionMap[exp->name] = func;
	}
	func->sfunc = exp;
	func->type = exp->type;
	int top = stack.size();
	CallInfo* cinfo = new CallInfo();
	cinfo->top = top;
	cinfo->type = exp->type;
	VariantInfo& res = stack.push();
	res.type = exp->type;
	res.name = exp->name;
	res.value = cinfo;
	for (int i = 0; i < exp->params.size(); i++)
	{
		BExp* param = exp->params[i];
		VariantInfo& var = stack.push();
		var.type = param->type;
		var.name = param->name;
		var.value = findClass(param->type);
		if (var.value.empty())
		{
			var.value = findEnum(param->type);
		}
		if (var.value.empty())
		{
			errorMessage(param) << "class " << param->type << " is undeclared.";
			raiseMessage(Signal_Message);
			continue;
		}
	}
	checkSubs(exp);
	stack.back(top);
	return !error;
}
bool member_BSource::checkSubs(BExp* exp)
{
	for (int i = 0; i < exp->subs.size(); i++)
	{
		checkExp(exp->subs[i]);
	}
	for (int i = 0; i < exp->subs.size(); i++)
	{
		if (BExp* sub = exp->subs[i])
		{
			if (sub->syntax == Syntax_If)
			{
				BExp* next = exp->subs(i + 1);
				if (next && next->syntax == Syntax_Else)
				{
					sub->params.append(next);
					i++;
				}
				continue;
			}
			if (sub->syntax == Syntax_Else)
			{
				errorMessage(sub) << "else should follow if .";
				raiseMessage(Signal_Message);
				continue;
			}
		}
	}
	return true;
}

BString member_BSource::checkFormula(BExpHolderArray& exps)
{
	BString type;
	if (exps.empty())
		return type;
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Opera && exp->name == "()")
		{
			exp->syntax = Syntax_None;
			if (exp->type.empty())
			{
				exp->type = checkFormula(exp->subs);
			}
		}
	}
	for (int i = 0; i < exps.size() - 1; i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Opera && exp->name == '.')
		{
			int end = i;
			BExp* last = 0;
			while (++end < exps.size())
			{
				last = exps(end);
				if (last->name == '.')
					continue;
				if (last->syntax == Syntax_Name)
					continue;
				break;
			}
			if (last->name == "()")
			{
				BExp* call = exps[end - 1];
				call->syntax = Syntax_Call;
				call->params = last->subs;
				call->subs.append(exps, i - 1, end - i - 1);
				exps.remove(end);
				exps.remove(i - 1, end - i);
				collateParams(call->params);
			}
			else if (end - i > 1)
			{
				BExp* name = new BExp();
				name->syntax = Syntax_Name;
				name->subs.append(exps, i, end - i);
				exps.remove(i, end);
				exps.insert(i, name);
			}
			continue;
		}
		if (exp->syntax == Syntax_Name || exp->syntax == Syntax_Self)
		{
			int end = i;
			BExp* last = 0;
			while (++end < exps.size())
			{
				last = exps(end);
				if (last->name == '.' || last->name == "->")
					continue;
				if (last->syntax == Syntax_Name)
					continue;
				if (last->syntax == Syntax_Self)
				{
					errorMessage(last) << "self should be first word of location.";
					raiseMessage(Signal_Message);
					return false;
				}
				break;
			}
			if (exp->syntax == Syntax_Self)
			{
				if (last->name == "()")
				{
					exp->subs.append(exps, i + 1, end - i - 2);
					BExp* call = exps[end - 1];
					call->syntax = Syntax_Call;
					call->params = last->subs;
					call->subs.reset();
					call->subs.append(exp);
					exps.remove(end);
					exps.remove(i, end - i - 1);
					collateParams(call->params);
				}
				else if (end - i > 1)
				{
					exp->subs.append(exps, i + 1, end - i - 1);
					exps.remove(i + 1, end - 1);
				}
				continue;
			}
			if (last->name == "()")
			{
				BExp* call = exps[end - 1];
				call->syntax = Syntax_Call;
				call->params = last->subs;
				call->subs.append(exps, i, end - i - 1);
				exps.remove(end);
				exps.remove(i, end - i - 1);
				collateParams(call->params);
			}
			else if (end - i > 1)
			{
				BExp* name = new BExp();
				name->syntax = Syntax_Name;
				name->subs.append(exps, i, end - i);
				exps.remove(i, end);
				exps.insert(i, name);
			}
			continue;
		}
	}
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* sub = exps[i];
		if (!sub)
			continue;
		if (sub->syntax != Syntax_Opera)
			continue;
		if (sub->name == '!')
		{
			BExp* next = exps(i + 1);
			checkExp(next);
			if (next && next->syntax != Syntax_Opera)
			{
				sub->syntax = Syntax_Test;
				sub->type = "bool";
				sub->value.clear();
				sub->params.append(next);
				exps.remove(i + 1);
				continue;
			}
			errorMessage(sub) << sub->name << " should used before value.";
			raiseMessage(Signal_Message);
			continue;
		}
		if (sub->name == '+' || sub->name == '-')
		{
			BExp* prev = exps(i - 1);
			BExp* next = exps(i + 1);
			if ((!prev || prev->syntax == Syntax_Opera) && next)
			{
				if (next->syntax == Syntax_Value)
				{
					exps.remove(sub);
					invertValue(next);
					continue;
				}
				if (next->syntax == Syntax_Key)
				{
					exps.remove(sub);
					int i = next->value;
					next->value = -i;
					continue;
				}
				if (checkExp(next) && next->type.size())
				{
					sub->subs.append(next);
					sub->value = Part_Left;
					sub->type = next->type;
					exps.remove(next);
					continue;
				}
			}
		}
		if (sub->name == "++" || sub->name == "--")
		{
			BExp* prev = exps(i - 1);
			BExp* next = exps(i + 1);
			if (prev && prev->syntax != Syntax_Opera)
			{
				sub->subs.append(prev);
				sub->value = Part_Right;
				exps.remove(i - 1);
				i--;
				continue;
			}
			if (next && next->syntax != Syntax_Opera)
			{
				sub->subs.append(next);
				sub->value = Part_Left;
				exps.remove(i + 1);
				i++;
				continue;
			}
			errorMessage(sub) << sub->name << " need host object.";
			raiseMessage(Signal_Message);
			continue;
		}
		if (sub->name == "[]")
		{
			if (BExp* prev = exps(i - 1))
			{
				BExp* front = exps(i - 2);
				if (front && front->syntax == Syntax_Type)
				{
					BExp* array = new BExp(Syntax_Array);
					array->type = "array";
					array->params.append(front);
					array->value = createTempClass(array);
					array->params = sub->subs;
					exps.replace(front, array);
				}
				else
				{
					sub->params = sub->subs;
					sub->subs.reset();
					sub->subs.append(prev);
					exps.remove(prev);
					i--;
				}
			}
			continue;
		}
	}
	for (int level = 0; level < 5; level++)
	{
		for (int i = 0; i < exps.size(); i++)
		{
			BExp* sub = exps(i);
			if (sub == 0)
				return false;
			if (sub->syntax == Syntax_Opera && sub->value == level)
			{
				if (BExp* next = exps(i + 1))
				{
					sub->params.append(next);
					exps.remove(next);
				}
				if (BExp* prev = exps(i - 1))
				{
					sub->subs.append(prev);
					exps.remove(prev);
					i--;
				}
			}
		}
	}
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* sub = exps(i);
		if (sub == 0)
			return false;
		if (sub->syntax == Syntax_And || sub->syntax == Syntax_Or)
		{
			if (BExp* next = exps(i + 1))
			{
				sub->params.append(next);
				exps.remove(next);
			}
			if (BExp* prev = exps(i - 1))
			{
				sub->subs.append(prev);
				exps.remove(prev);
				i--;
			}
		}
	}
	if (exps.size() == 1)
	{
		BExp* exp = exps.first();
		checkExp(exp);
		type = exp->type;
	}
	else
	{
		for (int i = 0; i < exps.size(); i++)
		{
			BExp* exp = exps[i];
			checkExp(exp);
		}
	}
	return type;
}
VariantInfo* member_BSource::findVariant(const BString& name)
{
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		if (vinfo.name == name)
			return &vinfo;
	}
	for (int i = 0; i < includes.size(); i++)
	{
		ILibrary* library = includes[i]->value;
		if (!library)
			continue;
		for (int i = 0; i < library->variants.size(); i++)
		{
			VariantInfo& vinfo = library->variants[i];
			if (vinfo.name == name)
				return &vinfo;
		}
	}
	for (int i = 0; i < script_member(script)->presetVariants.size(); i++)
	{
		VariantInfo& vinfo = script_member(script)->presetVariants[i];
		if (vinfo.name == name)
			return &vinfo;
	}
	return 0;
}
VariantInfo* member_BSource::findVariant(BExpHolderArray& exps)
{
	if (exps.empty())
		return 0;
	BExp* first = exps.first();
	if (first->syntax == Syntax_None)
	{
		BClass* cls = findClass(first->type);
		if (cls)
		{
			VariantInfo& var = stack.push();
			var.type = first->type;
			var.name = first->name;
			var.value = cls;
			return &var;
		}
		return 0;
	}
	VariantInfo* vinfo = findVariant(first->name);
	if (!vinfo)
	{
		errorMessage(first) << first->name << " is not declared.";
		raiseMessage(Signal_Message);
		return vinfo;
	}
	first->type = vinfo->type;
	for (int i = 1; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		BExp* prev = exps[i - 1];
		if (exp->name == '.')
		{
			if (prev->type.endWith('*'))
			{
				errorMessage(exp) << exp->name << " can't follow the pointer " << prev->type << ".";
				raiseMessage(Signal_Message);
			}
			exps.remove(i--);
			continue;
		}
		if (exp->name == "->")
		{
			if (!prev->type.endWith('*'))
			{
				errorMessage(exp) << exp->name << " should follow the pointer " << prev->type << ".";
				raiseMessage(Signal_Message);
			}
			exps.remove(i--);
			continue;
		}
		if (BClass* cls = findClass(vinfo->type))
		{
			vinfo = class_member(cls)->findVariant(exp->name);
			if (!vinfo)
			{
				errorMessage(exp) << cls->name() << " has no member " << exp->name << " is not declared.";
				raiseMessage(Signal_Message);
				break;
			}
			exp->type = vinfo->type;
		}
		else
		{
			errorMessage(exp) << vinfo->type << "::" << exp->name << " is not declared.";
			raiseMessage(Signal_Message);
			return 0;
		}
	}
	return vinfo;
}

int member_BSource::findSplit(BExpHolderArray& exps)
{
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Opera && exp->name == ',')
			return i;
	}
	return exps.size();
}
bool member_BSource::invertValue(BExp* exp)
{
	if (exp->type == "bool")
	{
		bool b = exp->value;
		exp->value = !b;
		return true;
	}
	if (exp->type == "char")
	{
		char c = exp->value;
		exp->value = -c;
		return true;
	}
	if (exp->type == "short")
	{
		short s = exp->value;
		exp->value = -s;
		return true;
	}
	if (exp->type == "int")
	{
		int i = exp->value;
		exp->value = -i;
		return true;
	}
	if (exp->type == "long")
	{
		int i = exp->value;
		exp->value = -i;
		return true;
	}
	if (exp->type == "real")
	{
		BReal r = exp->value;
		exp->value = -r;
		return true;
	}
	if (exp->type == "float")
	{
		float f = exp->value;
		exp->value = -f;
		return true;
	}
	if (exp->type == "double")
	{
		double d = exp->value;
		exp->value = -d;
		return true;
	}
	return false;
}

BClass* member_BSource::createTempClass(BExp* exp)
{
	if (exp->params.size())
	{
		BClass* cls = this->findClass(exp->type);
		if (!cls)
			return 0;
		if (class_member(cls)->tempTypes.size() != exp->params.size())
			return 0;
		exp->type << '<';
		for (int i = 0; i < exp->params.size(); i++)
		{
			if (BExp* param = exp->params[i])
				exp->type << param->type << ',';
		}
		exp->type -= ',';
		exp->type << '>';
		return this->findClass(exp->type);
	}
	return 0;
}
BClass* member_BSource::findSelf()
{
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		VariantInfo& vinfo = stack[i];
		if (CallInfo* cinfo = vinfo.value)
			return cinfo->self;
	}
	return 0;
}
BClass* member_BSource::findClass(const BString& type)
{
	if (type.endWith('&') || type.endWith('*') || type.beginWith("const "))
	{
		BString temp = type;
		if (type.endWith('&'))
			temp -= '&';
		if (type.endWith('*'))
			temp -= '*';
		if (type.beginWith("const "))
			temp.remove("const ");
		return findClass(temp);
	}
	if (BClass* cls = member_BScript::basicClassMap(type))
		return cls;
	if (BClass* cls = script_member(script)->presetClassMap(type))
		return cls;
	if (BClass* cls = classMap(type))
		return cls;
	if (type.endWith('>'))
	{
		int pos = type.find('<');
		if (pos < type.size())
		{
			BString ttype;
			type.substr(ttype, 0, pos);
			if (BClass* cls = this->findClass(ttype))
			{
				BClass* tmpcls = cls->clone();
				class_member(tmpcls)->instantiate(type);
				classMap[type] = tmpcls;
				return tmpcls;
			}
		}
	}
	return 0;
}
BEnum* member_BSource::findEnum(const BString& type)
{
	if (type.endWith('&') || type.endWith('*') || type.beginWith("const "))
	{
		BString temp = type;
		if (type.endWith('&'))
			temp -= '&';
		if (type.endWith('*'))
			temp -= '*';
		if (type.beginWith("const "))
			temp.remove("const ");
		return findEnum(temp);
	}
	if (BEnum* enm = script_member(script)->presetEnumMap.at(type))
		return enm;
	if (BEnum* enm = enumMap.at(type))
		return enm;
	return 0;
}
bool member_BSource::checkType(BClass* cls, const BString& type)
{
	if (type.endWith('&') || type.endWith('*') || type.beginWith("const "))
	{
		BString temp = type;
		if (type.endWith('&'))
			temp -= '&';
		if (type.endWith('*'))
			temp -= '*';
		if (type.beginWith("const "))
			temp.remove("const ");
		return cls->name() == temp;
	}
	return cls->name() == type;
}

BString member_BSource::funcName(BExp* exp)
{
	BString funcName;
	if (exp->syntax != Syntax_Decl)
	{
		funcName = exp->name;
	}
	funcName << '(';
	for (int i = 0; i < exp->params.size(); i++)
	{
		funcName << exp->params[i]->type << ',';
	}
	funcName -= ',';
	funcName << ')';
	return funcName;
}
FuncInfo* member_BSource::findFunction(BExp* exp)
{
	if (FuncInfo* finfo = script_member(script)->presetFunctionMap(exp->name))
		return finfo;
	if (FuncInfo* finfo = functionMap(exp->name))
		return finfo;

	BArray<ParamInfo> paramInfos;
	for (int i = 0; i < exp->params.size(); i++)
	{
		paramInfos.append(exp->params[i]->type);
	}

	for (int i = 0; i < includes.size(); i++)
	{
		ILibrary* library = includes[i]->value;
		if (!library)
			continue;
		for (auto it = library->functionMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			FuncInfo* finfo = it.value();
			if (name.beginWith(exp->name) && finfo->params.size() == exp->params.size())
			{
				if (matchFunction(paramInfos, finfo))
				{
					exp->name = name;
					exp->type = finfo->type;
					exp->value = finfo;
					for (int i = paramInfos.size(); i < finfo->params.size(); i++)
					{
						ParamInfo& pinfo = finfo->params[i];
						BExp* value = new BExp(Syntax_Value);
						value->type = pinfo.type;
						value->name = pinfo.name;
						value->value = pinfo.value;
						exp->params.append(value);
					}
					return finfo;
				}
			}
		}
	}
	for (auto it = script_member(script)->presetFunctionMap.begin(); it.valid(); ++it)
	{
		const BString& name = it.key();
		FuncInfo* finfo = it.value();
		if (name.beginWith(exp->name) && finfo->params.size() == exp->params.size())
		{
			if (matchFunction(paramInfos, finfo))
			{
				exp->name = name;
				exp->type = finfo->type;
				exp->value = finfo;
				for (int i = paramInfos.size(); i < finfo->params.size(); i++)
				{
					ParamInfo& pinfo = finfo->params[i];
					BExp* value = new BExp(Syntax_Value);
					value->type = pinfo.type;
					value->name = pinfo.name;
					value->value = pinfo.value;
					exp->params.append(value);
				}
				return finfo;
			}
		}
	}
	for (auto it = functionMap.begin(); it.valid(); ++it)
	{
		const BString& name = it.key();
		FuncInfo* finfo = it.value();
		if (name.beginWith(exp->name) && finfo->params.size() == exp->params.size())
		{
			if (matchFunction(paramInfos, finfo))
			{
				exp->name = name;
				exp->type = finfo->type;
				exp->value = finfo;
				return finfo;
			}
		}
	}

	BMap<BString, FuncInfo*> funcInfoMap;
	for (int i = 0; i < includes.size(); i++)
	{
		ILibrary* library = includes[i]->value;
		if (!library)
			continue;
		for (auto it = library->functionMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			if (!name.beginWith(exp->name))
				continue;
			int size = name.find('(');
			if (exp->name.size() != size)
				continue;
			FuncInfo* finfo = it.value();
			if (finfo->params.size() == exp->params.size())
			{
				bool valid = true;
				for (int i = 0; i < paramInfos.size(); i++)
				{
					ParamInfo& info = paramInfos[i];
					ParamInfo& pinfo = finfo->params[i];
					if (pinfo.type == "auto")
						continue;
					if (pinfo.type == info.type)
					{
						if (!pinfo.cnst && info.cnst)
						{
							valid = false;
							break;
						}
						continue;
					}
					if (!findConvertMethod(pinfo.type, info))
					{
						valid = false;
						break;
					}
				}
				if (valid)
				{
					funcInfoMap.insert(name, finfo);
				}
			}
		}
	}
	for (auto it = script_member(script)->presetFunctionMap.begin(); it.valid(); ++it)
	{
		const BString& name = it.key();
		if (!name.beginWith(exp->name))
			continue;
		int size = name.find('(');
		if (exp->name.size() != size)
			continue;
		FuncInfo* finfo = it.value();
		if (finfo->params.size() == exp->params.size())
		{
			bool valid = true;
			for (int i = 0; i < paramInfos.size(); i++)
			{
				ParamInfo& info = paramInfos[i];
				ParamInfo& pinfo = finfo->params[i];
				if (pinfo.type == "auto")
					continue;
				if (pinfo.type == info.type)
				{
					if (!pinfo.cnst && info.cnst)
					{
						valid = false;
						break;
					}
					continue;
				}
				if (!findConvertMethod(pinfo.type, info))
				{
					valid = false;
					break;
				}
			}
			if (valid)
			{
				funcInfoMap.insert(name, finfo);
			}
		}
	}
	for (auto it = functionMap.begin(); it.valid(); ++it)
	{
		const BString& name = it.key();
		if (!name.beginWith(exp->name))
			continue;
		int size = name.find('(');
		if (exp->name.size() != size)
			continue;
		FuncInfo* finfo = it.value();
		if (finfo->params.size() == exp->params.size())
		{
			bool valid = true;
			for (int i = 0; i < paramInfos.size(); i++)
			{
				ParamInfo& info = paramInfos[i];
				ParamInfo& pinfo = finfo->params[i];
				if (pinfo.type == "auto")
					continue;
				if (pinfo.type == info.type)
				{
					if (!pinfo.cnst && info.cnst)
					{
						valid = false;
						break;
					}
					continue;
				}
				if (!findConvertMethod(pinfo.type, info))
				{
					valid = false;
					break;
				}
			}
			if (valid)
			{
				funcInfoMap.insert(name, finfo);
			}
		}
	}
	if (funcInfoMap.size() == 1)
	{
		auto function = funcInfoMap.begin();
		FuncInfo* finfo = function.value();
		exp->type = finfo->type;
		exp->name = function.key();
		exp->value = finfo;

		for (int i = 0; i < paramInfos.size(); i++)
		{
			BExp* param = exp->params[i];
			ParamInfo& info = paramInfos[i];
			ParamInfo& pinfo = finfo->params[i];
			MethodInfo* minfo = findConvertMethod(pinfo.type, info);
			BExp* decl = new BExp(Syntax_Decl);
			decl->type = pinfo.type;
			decl->info = param->info;
			{
				BExp* init = new BExp(Syntax_Init);
				init->name << pinfo.type << "::" << pinfo.type << "(" << minfo->params[0].type << ")";
				init->value = minfo;
				decl->subs.append(param);
				decl->subs.append(init);
			}
			exp->params[i] = decl;
		}
		return finfo;
	}

	return 0;
}
MethodInfo* member_BSource::findMethod(BExp* exp, BClass* cls)
{
	BString fname = this->funcName(exp);
	if (MethodInfo* minfo = class_member(cls)->methodMap(fname))
	{
		exp->name.reset();
		exp->name << cls->name() << "::" << fname;
		exp->type = minfo->type;
		exp->value = minfo;
		return minfo;
	}

	bool cnst = exp->type.beginWith("const ");
	BArray<ParamInfo> paramInfos;
	for (int i = 0; i < exp->params.size(); i++)
	{
		ParamInfo& pinfo = paramInfos.append();
		pinfo.type = exp->params[i]->type;
		if (pinfo.type.beginWith("const "))
		{
			pinfo.type.remove("const ");
			pinfo.cnst = true;
		}
		if (pinfo.type.endWith('&') || pinfo.type.endWith('*'))
		{
			pinfo.refe = pinfo.type.last();
			pinfo.type -= pinfo.refe;
		}
	}
	for (auto it = class_member(cls)->methodMap.begin(); it.valid(); ++it)
	{
		const BString& name = it.key();
		if (!name.beginWith(exp->name))
			continue;
		int size = name.find('(');
		if (exp->name.size() != size)
			continue;
		MethodInfo* minfo = it.value();
		if (cnst && cnst != minfo->cnst)
			continue;
		if (minfo->params.size() < exp->params.size())
			continue;
		if (minfo->params.size() > exp->params.size())
		{
			ParamInfo& tail = minfo->params[exp->params.size()];
			if (!tail.defut)
				continue;
		}
		if (matchMethod(paramInfos, minfo))
		{
			exp->type = minfo->type;
			exp->name = name;
			exp->name.prepend("::");
			exp->name.prepend(cls->name());
			exp->value = minfo;
			for (int i = paramInfos.size(); i < minfo->params.size(); i++)
			{
				ParamInfo& pinfo = minfo->params[i];
				BExp* value = new BExp(Syntax_Value);
				value->type = pinfo.type;
				value->name = pinfo.name;
				value->value = pinfo.value;
				exp->params.append(value);
			}
			return minfo;
		}
	}

	BMap<BString, MethodInfo*> methodInfoMap;
	for (auto it = class_member(cls)->methodMap.begin(); it.valid(); ++it)
	{
		const BString& name = it.key();
		if (!name.beginWith(exp->name))
			continue;
		int size = name.find('(');
		if (exp->name.size() != size)
			continue;
		MethodInfo* minfo = it.value();
		if (cnst && cnst != minfo->cnst)
			continue;
		if (minfo->params.size() < exp->params.size())
			continue;
		if (minfo->params.size() > exp->params.size())
		{
			ParamInfo& tail = minfo->params[exp->params.size()];
			if (!tail.defut)
				continue;
		}
		bool valid = true;
		for (int i = 0; i < paramInfos.size(); i++)
		{
			ParamInfo& info = paramInfos[i];
			ParamInfo& pinfo = minfo->params[i];
			if (pinfo.type == "auto")
				continue;
			if (pinfo.type == info.type)
			{
				if (!pinfo.cnst && info.cnst)
				{
					valid = false;
					break;
				}
				continue;
			}
			if (!findConvertMethod(pinfo.type, info))
			{
				valid = false;
				break;
			}
		}
		if (valid)
		{
			methodInfoMap.insert(name, minfo);
		}
	}
	if (methodInfoMap.size() > 1 && !cnst)
	{
		MethodInfo* first = methodInfoMap.first();
		auto cnstIt = methodInfoMap.end();
		auto normIt = methodInfoMap.end();
		for (auto it = methodInfoMap.begin(); it.valid(); ++it)
		{
			MethodInfo* minfo = *it;
			if (minfo->name == first->name)
			{
				if (minfo->cnst)
					cnstIt = it;
				else
					normIt = it;
			}
		}
		if (cnstIt.valid() && normIt.valid())
		{
			methodInfoMap.erase(cnstIt);
		}
	}
	if (methodInfoMap.size() == 1)
	{
		auto method = methodInfoMap.begin();
		MethodInfo* minfo = method.value();
		exp->type = minfo->type;
		exp->name = method.key();
		exp->name.prepend("::");
		exp->name.prepend(cls->name());
		exp->value = minfo;

		for (int i = 0; i < paramInfos.size(); i++)
		{
			BExp* param = exp->params[i];
			ParamInfo& info = paramInfos[i];
			ParamInfo& pinfo = minfo->params[i];
			if (pinfo.type == "auto")
				continue;
			if (MethodInfo* conv_minfo = findConvertMethod(pinfo.type, info))
			{
				BExp* decl = new BExp(Syntax_Decl);
				decl->type = pinfo.type;
				decl->info = param->info;
				{
					BExp* init = new BExp(Syntax_Init);
					init->name << pinfo.type << "::" << pinfo.type << "(" << conv_minfo->params[0].type << ")";
					init->value = conv_minfo;
					decl->subs.append(param);
					decl->subs.append(init);
				}
				exp->params[i] = decl;
			}
		}
		for (int i = paramInfos.size(); i < minfo->params.size(); i++)
		{
			ParamInfo& pinfo = minfo->params[i];
			BExp* value = new BExp(Syntax_Value);
			value->type = pinfo.type;
			value->name = pinfo.name;
			value->value = pinfo.value;
			exp->params.append(value);
		}
		return minfo;
	}

	for (int i = 0; i < class_member(cls)->inherits.size(); i++)
	{
		if (BClass* up = class_member(cls)->inherits[i]->value)
		{
			if (MethodInfo* minfo = findMethod(exp, up))
				return minfo;
		}
	}
	return 0;
}
MethodInfo* member_BSource::findConvertMethod(const BString& type, ParamInfo& pinfo)
{
	if (BClass* cls = findClass(type))
	{
		for (auto it = class_member(cls)->methodMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			if (!name.beginWith(type))
				continue;
			MethodInfo* method = it.value();
			if (method->params.size() != 1)
				continue;
			if (method->params[0].type == pinfo.type)
				return method;
		}
	}
	return 0;
}
bool member_BSource::matchFunction(const ParamInfoArray& pinfos, FuncInfo* finfo)
{
	for (int i = 0; i < pinfos.size(); i++)
	{
		const ParamInfo& info = pinfos[i];
		ParamInfo& pinfo = finfo->params[i];
		if (pinfo.type == "auto")
			continue;
		if (pinfo.type == info.type)
		{
			if (!pinfo.cnst && info.cnst)
				return false;
			continue;
		}
		BClass* cls = this->findClass(info.type);
		if (cls && cls->isTyped(pinfo.type))
			continue;
		return false;
	}
	return true;
}
bool member_BSource::matchMethod(const ParamInfoArray& pinfos, MethodInfo* minfo)
{
	for (int i = 0; i < pinfos.size(); i++)
	{
		const ParamInfo& info = pinfos[i];
		ParamInfo& pinfo = minfo->params[i];
		if (pinfo.type == "auto")
			continue;
		if (pinfo.type == info.type)
		{
			if (!pinfo.cnst && info.cnst)
				return false;
			continue;
		}
		BClass* cls = this->findClass(info.type);
		if (cls && cls->isTyped(pinfo.type))
			continue;
		return false;
	}
	return true;
}
bool member_BSource::applyOpera(BExp* exp)
{
	if (MethodInfo* minfo = exp->value)
		return true;

	if (exp->type.empty())
		return false;

	if (exp->name == "==" || exp->name == "!=")
	{
		if (exp->subs.size() == 1)
		{
			BExp* sub = exp->subs.first();
			if (sub->type == "auto")
			{
				exp->syntax = Syntax_Equal;
				exp->type = "bool";
				return true;
			}
		}
		if (exp->params.size() == 1)
		{
			BExp* param = exp->params.first();
			if (param->type == "auto")
			{
				exp->syntax = Syntax_Equal;
				exp->type = "bool";
				return true;
			}
		}
	}

	BClass* cls = findClass(exp->type);
	if (!cls)
	{
		if (BEnum* enm = enumMap(exp->type))
		{
			if (BExp* param = exp->params.first())
			{
				if (param->type != exp->type && param->type != "int")
				{
					errorMessage(exp) << "assign " << param->type << " to " << exp->type << " failed.";
					raiseMessage(Signal_Message);
					return false;
				}
			}
			cls = findClass("int");
		}
	}
	if (!cls)
	{
		errorMessage(exp) << "class " << exp->type << " is not declared.";
		raiseMessage(Signal_Message);
		return false;
	}

	if (BExp* param = exp->params.first())
	{
		if (exp->type.endWith('&') && param->type.endWith('&'))
		{
			if (exp->type.contain(param->type))
			{
				exp->syntax = Syntax_Assign;
				return true;
			}
		}
	}

	if (findMethod(exp, cls))
		return true;

	if (BExp* param = exp->params.first())
	{
		BString funcName;
		if (BEnum* enm = enumMap(param->type))
		{
			funcName.reset();
			if (exp->syntax != Syntax_Decl)
			{
				funcName << exp->name;
			}
			funcName << '(' << "int" << ')';
			if (MethodInfo* minfo = class_member(cls)->methodMap(funcName))
			{
				exp->name = funcName;
				exp->name.prepend("::");
				exp->name.prepend(cls->name());
				exp->type = minfo->type;
				exp->value = minfo;
				return true;
			}
		}
	}

	BString fname = this->funcName(exp);
	exp->name.reset();
	exp->name << cls->name() << "::" << fname;
	errorMessage(exp) << exp->name << " operator is not declared.";
	raiseMessage(Signal_Message);
	return false;
}
